kernel/linux-2.6-v4l-dvb-experimen...

4036 lines
114 KiB
Diff
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From: Juan J. Garcia de Soria <skandalfo@gmail.com>
Subject: New rc-based driver for several ITE CIR's
This is a second version of an rc-core based driver for the ITE Tech IT8712F
CIR and now for a pair of other variants of the IT8512 CIR too.
This driver should replace the lirc_it87 and lirc_ite8709 currently living in
the LIRC staging directory.
The driver should support the ITE8704, ITE8713, ITE8708 and ITE8709 (this last
one yet untested) PNP ID's.
The code doesn'te reuse code from the pre-existing LIRC drivers, but has been
written from scratch using the nuvoton.cir driver as a skeleton.
This new driver shouldn't exhibit timing problems when running under load (or
with interrupts disabled for relatively long times). It works OOTB with the
RC6 MCE remote bundled with the ASUS EEEBox. TX support is implemented, but
I'm unable to test it since my hardware lacks TX capability.
Signed-off-by: Juan J. Garcia de Soria <skandalfo@gmail.com>
Tested-by: Stephan Raue <stephan@openelec.tv>
Signed-off-by: Jarod Wilson <jarod@redhat.com>
---
drivers/media/rc/Kconfig | 13 +
drivers/media/rc/Makefile | 1 +
drivers/media/rc/ite-cir.c | 1734 +++++++++++++++++++++++++++++++++++
drivers/media/rc/ite-cir.h | 478 ++++++++++
drivers/staging/lirc/Kconfig | 12 -
drivers/staging/lirc/Makefile | 2 -
drivers/staging/lirc/lirc_it87.c | 1027 ---------------------
drivers/staging/lirc/lirc_it87.h | 116 ---
drivers/staging/lirc/lirc_ite8709.c | 542 -----------
9 files changed, 2226 insertions(+), 1699 deletions(-)
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
index 3785162..0615443 100644
--- a/drivers/media/rc/Kconfig
+++ b/drivers/media/rc/Kconfig
@@ -135,6 +135,19 @@ config IR_MCEUSB
To compile this driver as a module, choose M here: the
module will be called mceusb.
+config IR_ITE_CIR
+ tristate "ITE Tech Inc. IT8712/IT8512 Consumer Infrared Transceiver"
+ depends on PNP
+ depends on RC_CORE
+ ---help---
+ Say Y here to enable support for integrated infrared receivers
+ /transceivers made by ITE Tech Inc. These are found in
+ several ASUS devices, like the ASUS Digimatrix or the ASUS
+ EEEBox 1501U.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ite-cir.
+
config IR_NUVOTON
tristate "Nuvoton w836x7hg Consumer Infrared Transceiver"
depends on PNP
diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile
index 67b4f7f..c6cfe70 100644
--- a/drivers/media/rc/Makefile
+++ b/drivers/media/rc/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o
# stand-alone IR receivers/transmitters
obj-$(CONFIG_IR_IMON) += imon.o
+obj-$(CONFIG_IR_ITE_CIR) += ite-cir.o
obj-$(CONFIG_IR_MCEUSB) += mceusb.o
obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o
obj-$(CONFIG_IR_ENE) += ene_ir.o
diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c
new file mode 100644
index 0000000..7970195
--- /dev/null
+++ b/drivers/media/rc/ite-cir.c
@@ -0,0 +1,1734 @@
+/*
+ * Driver for ITE Tech Inc. IT8712F/IT8512 CIR
+ *
+ * Copyright (C) 2010 Juan Jesús García de Soria <skandalfo@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.
+ *
+ * Inspired by the original lirc_it87 and lirc_ite8709 drivers, on top of the
+ * skeleton provided by the nuvoton-cir driver.
+ *
+ * The lirc_it87 driver was originally written by Hans-Gunter Lutke Uphues
+ * <hg_lu@web.de> in 2001, with enhancements by Christoph Bartelmus
+ * <lirc@bartelmus.de>, Andrew Calkin <r_tay@hotmail.com> and James Edwards
+ * <jimbo-lirc@edwardsclan.net>.
+ *
+ * The lirc_ite8709 driver was written by Grégory Lardière
+ * <spmf2004-lirc@yahoo.fr> in 2008.
+ */
+
+#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 <linux/bitops.h>
+#include <media/rc-core.h>
+#include <linux/pci_ids.h>
+
+#include "ite-cir.h"
+
+/* module parameters */
+
+/* debug level */
+static int debug;
+module_param(debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable debugging output");
+
+/* low limit for RX carrier freq, Hz, 0 for no RX demodulation */
+static int rx_low_carrier_freq;
+module_param(rx_low_carrier_freq, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(rx_low_carrier_freq, "Override low RX carrier frequency, Hz, "
+ "0 for no RX demodulation");
+
+/* high limit for RX carrier freq, Hz, 0 for no RX demodulation */
+static int rx_high_carrier_freq;
+module_param(rx_high_carrier_freq, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(rx_high_carrier_freq, "Override high RX carrier frequency, "
+ "Hz, 0 for no RX demodulation");
+
+/* override tx carrier frequency */
+static int tx_carrier_freq;
+module_param(tx_carrier_freq, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(tx_carrier_freq, "Override TX carrier frequency, Hz");
+
+/* override tx duty cycle */
+static int tx_duty_cycle;
+module_param(tx_duty_cycle, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(tx_duty_cycle, "Override TX duty cycle, 1-100");
+
+/* override default sample period */
+static long sample_period;
+module_param(sample_period, long, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(sample_period, "Override carrier sample period, us");
+
+/* override detected model id */
+static int model_number = -1;
+module_param(model_number, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(model_number, "Use this model number, don't autodetect");
+
+
+/* HW-independent code functions */
+
+/* check whether carrier frequency is high frequency */
+static inline bool ite_is_high_carrier_freq(unsigned int freq)
+{
+ return freq >= ITE_HCF_MIN_CARRIER_FREQ;
+}
+
+/* get the bits required to program the carrier frequency in CFQ bits,
+ * unshifted */
+static u8 ite_get_carrier_freq_bits(unsigned int freq)
+{
+ if (ite_is_high_carrier_freq(freq)) {
+ if (freq < 425000)
+ return ITE_CFQ_400;
+
+ else if (freq < 465000)
+ return ITE_CFQ_450;
+
+ else if (freq < 490000)
+ return ITE_CFQ_480;
+
+ else
+ return ITE_CFQ_500;
+ } else {
+ /* trim to limits */
+ if (freq < ITE_LCF_MIN_CARRIER_FREQ)
+ freq = ITE_LCF_MIN_CARRIER_FREQ;
+ if (freq > ITE_LCF_MAX_CARRIER_FREQ)
+ freq = ITE_LCF_MAX_CARRIER_FREQ;
+
+ /* convert to kHz and subtract the base freq */
+ freq =
+ DIV_ROUND_CLOSEST(freq - ITE_LCF_MIN_CARRIER_FREQ,
+ 1000);
+
+ return (u8) freq;
+ }
+}
+
+/* get the bits required to program the pulse with in TXMPW */
+static u8 ite_get_pulse_width_bits(unsigned int freq, int duty_cycle)
+{
+ unsigned long period_ns, on_ns;
+
+ /* sanitize freq into range */
+ if (freq < ITE_LCF_MIN_CARRIER_FREQ)
+ freq = ITE_LCF_MIN_CARRIER_FREQ;
+ if (freq > ITE_HCF_MAX_CARRIER_FREQ)
+ freq = ITE_HCF_MAX_CARRIER_FREQ;
+
+ period_ns = 1000000000UL / freq;
+ on_ns = period_ns * duty_cycle / 100;
+
+ if (ite_is_high_carrier_freq(freq)) {
+ if (on_ns < 750)
+ return ITE_TXMPW_A;
+
+ else if (on_ns < 850)
+ return ITE_TXMPW_B;
+
+ else if (on_ns < 950)
+ return ITE_TXMPW_C;
+
+ else if (on_ns < 1080)
+ return ITE_TXMPW_D;
+
+ else
+ return ITE_TXMPW_E;
+ } else {
+ if (on_ns < 6500)
+ return ITE_TXMPW_A;
+
+ else if (on_ns < 7850)
+ return ITE_TXMPW_B;
+
+ else if (on_ns < 9650)
+ return ITE_TXMPW_C;
+
+ else if (on_ns < 11950)
+ return ITE_TXMPW_D;
+
+ else
+ return ITE_TXMPW_E;
+ }
+}
+
+/* decode raw bytes as received by the hardware, and push them to the ir-core
+ * layer */
+static void ite_decode_bytes(struct ite_dev *dev, const u8 * data, int
+ length)
+{
+ u32 sample_period;
+ unsigned long *ldata;
+ unsigned int next_one, next_zero, size;
+ DEFINE_IR_RAW_EVENT(ev);
+
+ if (length == 0)
+ return;
+
+ sample_period = dev->params.sample_period;
+ ldata = (unsigned long *)data;
+ size = length << 3;
+ next_one = generic_find_next_le_bit(ldata, size, 0);
+ if (next_one > 0) {
+ ev.pulse = true;
+ ev.duration =
+ ITE_BITS_TO_NS(next_one, sample_period);
+ ir_raw_event_store_with_filter(dev->rdev, &ev);
+ }
+
+ while (next_one < size) {
+ next_zero = generic_find_next_zero_le_bit(ldata, size, next_one + 1);
+ ev.pulse = false;
+ ev.duration = ITE_BITS_TO_NS(next_zero - next_one, sample_period);
+ ir_raw_event_store_with_filter(dev->rdev, &ev);
+
+ if (next_zero < size) {
+ next_one =
+ generic_find_next_le_bit(ldata,
+ size,
+ next_zero + 1);
+ ev.pulse = true;
+ ev.duration =
+ ITE_BITS_TO_NS(next_one - next_zero,
+ sample_period);
+ ir_raw_event_store_with_filter
+ (dev->rdev, &ev);
+ } else
+ next_one = size;
+ }
+
+ ir_raw_event_handle(dev->rdev);
+
+ ite_dbg_verbose("decoded %d bytes.", length);
+}
+
+/* set all the rx/tx carrier parameters; this must be called with the device
+ * spinlock held */
+static void ite_set_carrier_params(struct ite_dev *dev)
+{
+ unsigned int freq, low_freq, high_freq;
+ int allowance;
+ bool use_demodulator;
+ bool for_tx = dev->transmitting;
+
+ ite_dbg("%s called", __func__);
+
+ if (for_tx) {
+ /* we don't need no stinking calculations */
+ freq = dev->params.tx_carrier_freq;
+ allowance = ITE_RXDCR_DEFAULT;
+ use_demodulator = false;
+ } else {
+ low_freq = dev->params.rx_low_carrier_freq;
+ high_freq = dev->params.rx_high_carrier_freq;
+
+ if (low_freq == 0) {
+ /* don't demodulate */
+ freq =
+ ITE_DEFAULT_CARRIER_FREQ;
+ allowance = ITE_RXDCR_DEFAULT;
+ use_demodulator = false;
+ } else {
+ /* calculate the middle freq */
+ freq = (low_freq + high_freq) / 2;
+
+ /* calculate the allowance */
+ allowance =
+ DIV_ROUND_CLOSEST(10000 * (high_freq - low_freq),
+ ITE_RXDCR_PER_10000_STEP
+ * (high_freq + low_freq));
+
+ if (allowance < 1)
+ allowance = 1;
+
+ if (allowance > ITE_RXDCR_MAX)
+ allowance = ITE_RXDCR_MAX;
+ }
+ }
+
+ /* set the carrier parameters in a device-dependent way */
+ dev->params.set_carrier_params(dev, ite_is_high_carrier_freq(freq),
+ use_demodulator, ite_get_carrier_freq_bits(freq), allowance,
+ ite_get_pulse_width_bits(freq, dev->params.tx_duty_cycle));
+}
+
+/* interrupt service routine for incoming and outgoing CIR data */
+static irqreturn_t ite_cir_isr(int irq, void *data)
+{
+ struct ite_dev *dev = data;
+ unsigned long flags;
+ irqreturn_t ret = IRQ_RETVAL(IRQ_NONE);
+ u8 rx_buf[ITE_RX_FIFO_LEN];
+ int rx_bytes;
+ int iflags;
+
+ ite_dbg_verbose("%s firing", __func__);
+
+ /* grab the spinlock */
+ spin_lock_irqsave(&dev->lock, flags);
+
+ /* read the interrupt flags */
+ iflags = dev->params.get_irq_causes(dev);
+
+ /* check for the receive interrupt */
+ if (iflags & (ITE_IRQ_RX_FIFO | ITE_IRQ_RX_FIFO_OVERRUN)) {
+ /* read the FIFO bytes */
+ rx_bytes =
+ dev->params.get_rx_bytes(dev, rx_buf,
+ ITE_RX_FIFO_LEN);
+
+ if (rx_bytes > 0) {
+ /* drop the spinlock, since the ir-core layer
+ * may call us back again through
+ * ite_s_idle() */
+ spin_unlock_irqrestore(&dev->
+ lock,
+ flags);
+
+ /* decode the data we've just received */
+ ite_decode_bytes(dev, rx_buf,
+ rx_bytes);
+
+ /* reacquire the spinlock */
+ spin_lock_irqsave(&dev->lock,
+ flags);
+
+ /* mark the interrupt as serviced */
+ ret = IRQ_RETVAL(IRQ_HANDLED);
+ }
+ } else if (iflags & ITE_IRQ_TX_FIFO) {
+ /* FIFO space available interrupt */
+ ite_dbg_verbose("got interrupt for TX FIFO");
+
+ /* wake any sleeping transmitter */
+ wake_up_interruptible(&dev->tx_queue);
+
+ /* mark the interrupt as serviced */
+ ret = IRQ_RETVAL(IRQ_HANDLED);
+ }
+
+ /* drop the spinlock */
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ ite_dbg_verbose("%s done returning %d", __func__, (int)ret);
+
+ return ret;
+}
+
+/* set the rx carrier freq range, guess it's in Hz... */
+static int ite_set_rx_carrier_range(struct rc_dev *rcdev, u32 carrier_low, u32
+ carrier_high)
+{
+ unsigned long flags;
+ struct ite_dev *dev = rcdev->priv;
+
+ spin_lock_irqsave(&dev->lock, flags);
+ dev->params.rx_low_carrier_freq = carrier_low;
+ dev->params.rx_high_carrier_freq = carrier_high;
+ ite_set_carrier_params(dev);
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ return 0;
+}
+
+/* set the tx carrier freq, guess it's in Hz... */
+static int ite_set_tx_carrier(struct rc_dev *rcdev, u32 carrier)
+{
+ unsigned long flags;
+ struct ite_dev *dev = rcdev->priv;
+
+ spin_lock_irqsave(&dev->lock, flags);
+ dev->params.tx_carrier_freq = carrier;
+ ite_set_carrier_params(dev);
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ return 0;
+}
+
+/* set the tx duty cycle by controlling the pulse width */
+static int ite_set_tx_duty_cycle(struct rc_dev *rcdev, u32 duty_cycle)
+{
+ unsigned long flags;
+ struct ite_dev *dev = rcdev->priv;
+
+ spin_lock_irqsave(&dev->lock, flags);
+ dev->params.tx_duty_cycle = duty_cycle;
+ ite_set_carrier_params(dev);
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ return 0;
+}
+
+/* transmit out IR pulses; what you get here is a batch of alternating
+ * pulse/space/pulse/space lengths that we should write out completely through
+ * the FIFO, blocking on a full FIFO */
+static int ite_tx_ir(struct rc_dev *rcdev, int *txbuf, u32 n)
+{
+ unsigned long flags;
+ struct ite_dev *dev = rcdev->priv;
+ bool is_pulse = false;
+ int remaining_us, fifo_avail, fifo_remaining, last_idx = 0;
+ int max_rle_us, next_rle_us;
+ int ret = n;
+ u8 last_sent[ITE_TX_FIFO_LEN];
+ u8 val;
+
+ ite_dbg("%s called", __func__);
+
+ /* clear the array just in case */
+ memset(last_sent, 0, ARRAY_SIZE(last_sent));
+
+ /* n comes in bytes; convert to ints */
+ n /= sizeof(int);
+
+ spin_lock_irqsave(&dev->lock, flags);
+
+ /* let everybody know we're now transmitting */
+ dev->transmitting = true;
+
+ /* and set the carrier values for transmission */
+ ite_set_carrier_params(dev);
+
+ /* calculate how much time we can send in one byte */
+ max_rle_us =
+ (ITE_BAUDRATE_DIVISOR * dev->params.sample_period *
+ ITE_TX_MAX_RLE) / 1000;
+
+ /* disable the receiver */
+ dev->params.disable_rx(dev);
+
+ /* this is where we'll begin filling in the FIFO, until it's full.
+ * then we'll just activate the interrupt, wait for it to wake us up
+ * again, disable it, continue filling the FIFO... until everything
+ * has been pushed out */
+ fifo_avail =
+ ITE_TX_FIFO_LEN - dev->params.get_tx_used_slots(dev);
+
+ while (n > 0 && dev->in_use) {
+ /* transmit the next sample */
+ is_pulse = !is_pulse;
+ remaining_us = *(txbuf++);
+ n--;
+
+ ite_dbg("%s: %ld",
+ ((is_pulse) ? "pulse" : "space"),
+ (long int)
+ remaining_us);
+
+ /* repeat while the pulse is non-zero length */
+ while (remaining_us > 0 && dev->in_use) {
+ if (remaining_us > max_rle_us)
+ next_rle_us = max_rle_us;
+
+ else
+ next_rle_us = remaining_us;
+
+ remaining_us -= next_rle_us;
+
+ /* check what's the length we have to pump out */
+ val = (ITE_TX_MAX_RLE * next_rle_us) / max_rle_us;
+
+ /* put it into the sent buffer */
+ last_sent[last_idx++] = val;
+ last_idx &= (ITE_TX_FIFO_LEN);
+
+ /* encode it for 7 bits */
+ val = (val - 1) & ITE_TX_RLE_MASK;
+
+ /* take into account pulse/space prefix */
+ if (is_pulse)
+ val |= ITE_TX_PULSE;
+
+ else
+ val |= ITE_TX_SPACE;
+
+ /* if we get to 0 available, read again, just in case
+ * some other slot got freed */
+ if (fifo_avail <= 0)
+ fifo_avail = ITE_TX_FIFO_LEN - dev->params.get_tx_used_slots(dev);
+
+ /* if it's still full */
+ if (fifo_avail <= 0) {
+ /* enable the tx interrupt */
+ dev->params.
+ enable_tx_interrupt(dev);
+
+ /* drop the spinlock */
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ /* wait for the FIFO to empty enough */
+ wait_event_interruptible(dev->tx_queue, (fifo_avail = ITE_TX_FIFO_LEN - dev->params.get_tx_used_slots(dev)) >= 8);
+
+ /* get the spinlock again */
+ spin_lock_irqsave(&dev->lock, flags);
+
+ /* disable the tx interrupt again. */
+ dev->params.
+ disable_tx_interrupt(dev);
+ }
+
+ /* now send the byte through the FIFO */
+ dev->params.put_tx_byte(dev, val);
+ fifo_avail--;
+ }
+ }
+
+ /* wait and don't return until the whole FIFO has been sent out;
+ * otherwise we could configure the RX carrier params instead of the
+ * TX ones while the transmission is still being performed! */
+ fifo_remaining = dev->params.get_tx_used_slots(dev);
+ remaining_us = 0;
+ while (fifo_remaining > 0) {
+ fifo_remaining--;
+ last_idx--;
+ last_idx &= (ITE_TX_FIFO_LEN - 1);
+ remaining_us += last_sent[last_idx];
+ }
+ remaining_us = (remaining_us * max_rle_us) / (ITE_TX_MAX_RLE);
+
+ /* drop the spinlock while we sleep */
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ /* sleep remaining_us microseconds */
+ mdelay(DIV_ROUND_UP(remaining_us, 1000));
+
+ /* reacquire the spinlock */
+ spin_lock_irqsave(&dev->lock, flags);
+
+ /* now we're not transmitting anymore */
+ dev->transmitting = false;
+
+ /* and set the carrier values for reception */
+ ite_set_carrier_params(dev);
+
+ /* reenable the receiver */
+ if (dev->in_use)
+ dev->params.enable_rx(dev);
+
+ /* notify transmission end */
+ wake_up_interruptible(&dev->tx_ended);
+
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ return ret;
+}
+
+/* idle the receiver if needed */
+static void ite_s_idle(struct rc_dev *rcdev, bool enable)
+{
+ unsigned long flags;
+ struct ite_dev *dev = rcdev->priv;
+
+ ite_dbg("%s called", __func__);
+
+ if (enable) {
+ spin_lock_irqsave(&dev->lock, flags);
+ dev->params.idle_rx(dev);
+ spin_unlock_irqrestore(&dev->lock, flags);
+ }
+}
+
+
+/* IT8712F HW-specific functions */
+
+/* retrieve a bitmask of the current causes for a pending interrupt; this may
+ * be composed of ITE_IRQ_TX_FIFO, ITE_IRQ_RX_FIFO and ITE_IRQ_RX_FIFO_OVERRUN
+ * */
+static int it87_get_irq_causes(struct ite_dev *dev)
+{
+ u8 iflags;
+ int ret = 0;
+
+ ite_dbg("%s called", __func__);
+
+ /* read the interrupt flags */
+ iflags = inb(dev->cir_addr + IT87_IIR) & IT87_II;
+
+ switch (iflags) {
+ case IT87_II_RXDS:
+ ret = ITE_IRQ_RX_FIFO;
+ break;
+ case IT87_II_RXFO:
+ ret = ITE_IRQ_RX_FIFO_OVERRUN;
+ break;
+ case IT87_II_TXLDL:
+ ret = ITE_IRQ_TX_FIFO;
+ break;
+ }
+
+ return ret;
+}
+
+/* set the carrier parameters; to be called with the spinlock held */
+static void it87_set_carrier_params(struct ite_dev *dev, bool high_freq,
+ bool use_demodulator,
+ u8 carrier_freq_bits, u8 allowance_bits,
+ u8 pulse_width_bits)
+{
+ u8 val;
+
+ ite_dbg("%s called", __func__);
+
+ /* program the RCR register */
+ val = inb(dev->cir_addr + IT87_RCR)
+ & ~(IT87_HCFS | IT87_RXEND | IT87_RXDCR);
+
+ if (high_freq)
+ val |= IT87_HCFS;
+
+ if (use_demodulator)
+ val |= IT87_RXEND;
+
+ val |= allowance_bits;
+
+ outb(val, dev->cir_addr + IT87_RCR);
+
+ /* program the TCR2 register */
+ outb((carrier_freq_bits << IT87_CFQ_SHIFT) | pulse_width_bits,
+ dev->cir_addr + IT87_TCR2);
+}
+
+/* read up to buf_size bytes from the RX FIFO; to be called with the spinlock
+ * held */
+static int it87_get_rx_bytes(struct ite_dev *dev, u8 * buf, int buf_size)
+{
+ int fifo, read = 0;
+
+ ite_dbg("%s called", __func__);
+
+ /* read how many bytes are still in the FIFO */
+ fifo = inb(dev->cir_addr + IT87_RSR) & IT87_RXFBC;
+
+ while (fifo > 0 && buf_size > 0) {
+ *(buf++) = inb(dev->cir_addr + IT87_DR);
+ fifo--;
+ read++;
+ buf_size--;
+ }
+
+ return read;
+}
+
+/* return how many bytes are still in the FIFO; this will be called
+ * with the device spinlock NOT HELD while waiting for the TX FIFO to get
+ * empty; let's expect this won't be a problem */
+static int it87_get_tx_used_slots(struct ite_dev *dev)
+{
+ ite_dbg("%s called", __func__);
+
+ return inb(dev->cir_addr + IT87_TSR) & IT87_TXFBC;
+}
+
+/* put a byte to the TX fifo; this should be called with the spinlock held */
+static void it87_put_tx_byte(struct ite_dev *dev, u8 value)
+{
+ outb(value, dev->cir_addr + IT87_DR);
+}
+
+/* idle the receiver so that we won't receive samples until another
+ pulse is detected; this must be called with the device spinlock held */
+static void it87_idle_rx(struct ite_dev *dev)
+{
+ ite_dbg("%s called", __func__);
+
+ /* disable streaming by clearing RXACT writing it as 1 */
+ outb(inb(dev->cir_addr + IT87_RCR) | IT87_RXACT,
+ dev->cir_addr + IT87_RCR);
+
+ /* clear the FIFO */
+ outb(inb(dev->cir_addr + IT87_TCR1) | IT87_FIFOCLR,
+ dev->cir_addr + IT87_TCR1);
+}
+
+/* disable the receiver; this must be called with the device spinlock held */
+static void it87_disable_rx(struct ite_dev *dev)
+{
+ ite_dbg("%s called", __func__);
+
+ /* disable the receiver interrupts */
+ outb(inb(dev->cir_addr + IT87_IER) & ~(IT87_RDAIE | IT87_RFOIE),
+ dev->cir_addr + IT87_IER);
+
+ /* disable the receiver */
+ outb(inb(dev->cir_addr + IT87_RCR) & ~IT87_RXEN,
+ dev->cir_addr + IT87_RCR);
+
+ /* clear the FIFO and RXACT (actually RXACT should have been cleared
+ * in the previous outb() call) */
+ it87_idle_rx(dev);
+}
+
+/* enable the receiver; this must be called with the device spinlock held */
+static void it87_enable_rx(struct ite_dev *dev)
+{
+ ite_dbg("%s called", __func__);
+
+ /* enable the receiver by setting RXEN */
+ outb(inb(dev->cir_addr + IT87_RCR) | IT87_RXEN,
+ dev->cir_addr + IT87_RCR);
+
+ /* just prepare it to idle for the next reception */
+ it87_idle_rx(dev);
+
+ /* enable the receiver interrupts and master enable flag */
+ outb(inb(dev->cir_addr + IT87_IER) | IT87_RDAIE | IT87_RFOIE | IT87_IEC,
+ dev->cir_addr + IT87_IER);
+}
+
+/* disable the transmitter interrupt; this must be called with the device
+ * spinlock held */
+static void it87_disable_tx_interrupt(struct ite_dev *dev)
+{
+ ite_dbg("%s called", __func__);
+
+ /* disable the transmitter interrupts */
+ outb(inb(dev->cir_addr + IT87_IER) & ~IT87_TLDLIE,
+ dev->cir_addr + IT87_IER);
+}
+
+/* enable the transmitter interrupt; this must be called with the device
+ * spinlock held */
+static void it87_enable_tx_interrupt(struct ite_dev *dev)
+{
+ ite_dbg("%s called", __func__);
+
+ /* enable the transmitter interrupts and master enable flag */
+ outb(inb(dev->cir_addr + IT87_IER) | IT87_TLDLIE | IT87_IEC,
+ dev->cir_addr + IT87_IER);
+}
+
+/* disable the device; this must be called with the device spinlock held */
+static void it87_disable(struct ite_dev *dev)
+{
+ ite_dbg("%s called", __func__);
+
+ /* clear out all interrupt enable flags */
+ outb(inb(dev->cir_addr + IT87_IER) &
+ ~(IT87_IEC | IT87_RFOIE | IT87_RDAIE | IT87_TLDLIE),
+ dev->cir_addr + IT87_IER);
+
+ /* disable the receiver */
+ it87_disable_rx(dev);
+
+ /* erase the FIFO */
+ outb(IT87_FIFOCLR | inb(dev->cir_addr + IT87_TCR1),
+ dev->cir_addr + IT87_TCR1);
+}
+
+/* initialize the hardware */
+static void it87_init_hardware(struct ite_dev *dev)
+{
+ ite_dbg("%s called", __func__);
+
+ /* enable just the baud rate divisor register,
+ disabling all the interrupts at the same time */
+ outb((inb(dev->cir_addr + IT87_IER) &
+ ~(IT87_IEC | IT87_RFOIE | IT87_RDAIE | IT87_TLDLIE)) | IT87_BR,
+ dev->cir_addr + IT87_IER);
+
+ /* write out the baud rate divisor */
+ outb(ITE_BAUDRATE_DIVISOR & 0xff, dev->cir_addr + IT87_BDLR);
+ outb((ITE_BAUDRATE_DIVISOR >> 8) & 0xff, dev->cir_addr + IT87_BDHR);
+
+ /* disable the baud rate divisor register again */
+ outb(inb(dev->cir_addr + IT87_IER) & ~IT87_BR,
+ dev->cir_addr + IT87_IER);
+
+ /* program the RCR register defaults */
+ outb(ITE_RXDCR_DEFAULT, dev->cir_addr + IT87_RCR);
+
+ /* program the TCR1 register */
+ outb(IT87_TXMPM_DEFAULT | IT87_TXENDF | IT87_TXRLE
+ | IT87_FIFOTL_DEFAULT | IT87_FIFOCLR,
+ dev->cir_addr + IT87_TCR1);
+
+ /* program the carrier parameters */
+ ite_set_carrier_params(dev);
+}
+
+/* IT8512F on ITE8708 HW-specific functions */
+
+/* retrieve a bitmask of the current causes for a pending interrupt; this may
+ * be composed of ITE_IRQ_TX_FIFO, ITE_IRQ_RX_FIFO and ITE_IRQ_RX_FIFO_OVERRUN
+ * */
+static int it8708_get_irq_causes(struct ite_dev *dev)
+{
+ u8 iflags;
+ int ret = 0;
+
+ ite_dbg("%s called", __func__);
+
+ /* read the interrupt flags */
+ iflags = inb(dev->cir_addr + IT8708_C0IIR);
+
+ if (iflags & IT85_TLDLI)
+ ret |= ITE_IRQ_TX_FIFO;
+ if (iflags & IT85_RDAI)
+ ret |= ITE_IRQ_RX_FIFO;
+ if (iflags & IT85_RFOI)
+ ret |= ITE_IRQ_RX_FIFO_OVERRUN;
+
+ return ret;
+}
+
+/* set the carrier parameters; to be called with the spinlock held */
+static void it8708_set_carrier_params(struct ite_dev *dev, bool high_freq,
+ bool use_demodulator,
+ u8 carrier_freq_bits, u8 allowance_bits,
+ u8 pulse_width_bits)
+{
+ u8 val;
+
+ ite_dbg("%s called", __func__);
+
+ /* program the C0CFR register, with HRAE=1 */
+ outb(inb(dev->cir_addr + IT8708_BANKSEL) | IT8708_HRAE,
+ dev->cir_addr + IT8708_BANKSEL);
+
+ val = (inb(dev->cir_addr + IT8708_C0CFR)
+ & ~(IT85_HCFS | IT85_CFQ)) | carrier_freq_bits;
+
+ if (high_freq)
+ val |= IT85_HCFS;
+
+ outb(val, dev->cir_addr + IT8708_C0CFR);
+
+ outb(inb(dev->cir_addr + IT8708_BANKSEL) & ~IT8708_HRAE,
+ dev->cir_addr + IT8708_BANKSEL);
+
+ /* program the C0RCR register */
+ val = inb(dev->cir_addr + IT8708_C0RCR)
+ & ~(IT85_RXEND | IT85_RXDCR);
+
+ if (use_demodulator)
+ val |= IT85_RXEND;
+
+ val |= allowance_bits;
+
+ outb(val, dev->cir_addr + IT8708_C0RCR);
+
+ /* program the C0TCR register */
+ val = inb(dev->cir_addr + IT8708_C0TCR) & ~IT85_TXMPW;
+ val |= pulse_width_bits;
+ outb(val, dev->cir_addr + IT8708_C0TCR);
+}
+
+/* read up to buf_size bytes from the RX FIFO; to be called with the spinlock
+ * held */
+static int it8708_get_rx_bytes(struct ite_dev *dev, u8 * buf, int buf_size)
+{
+ int fifo, read = 0;
+
+ ite_dbg("%s called", __func__);
+
+ /* read how many bytes are still in the FIFO */
+ fifo = inb(dev->cir_addr + IT8708_C0RFSR) & IT85_RXFBC;
+
+ while (fifo > 0 && buf_size > 0) {
+ *(buf++) = inb(dev->cir_addr + IT8708_C0DR);
+ fifo--;
+ read++;
+ buf_size--;
+ }
+
+ return read;
+}
+
+/* return how many bytes are still in the FIFO; this will be called
+ * with the device spinlock NOT HELD while waiting for the TX FIFO to get
+ * empty; let's expect this won't be a problem */
+static int it8708_get_tx_used_slots(struct ite_dev *dev)
+{
+ ite_dbg("%s called", __func__);
+
+ return inb(dev->cir_addr + IT8708_C0TFSR) & IT85_TXFBC;
+}
+
+/* put a byte to the TX fifo; this should be called with the spinlock held */
+static void it8708_put_tx_byte(struct ite_dev *dev, u8 value)
+{
+ outb(value, dev->cir_addr + IT8708_C0DR);
+}
+
+/* idle the receiver so that we won't receive samples until another
+ pulse is detected; this must be called with the device spinlock held */
+static void it8708_idle_rx(struct ite_dev *dev)
+{
+ ite_dbg("%s called", __func__);
+
+ /* disable streaming by clearing RXACT writing it as 1 */
+ outb(inb(dev->cir_addr + IT8708_C0RCR) | IT85_RXACT,
+ dev->cir_addr + IT8708_C0RCR);
+
+ /* clear the FIFO */
+ outb(inb(dev->cir_addr + IT8708_C0MSTCR) | IT85_FIFOCLR,
+ dev->cir_addr + IT8708_C0MSTCR);
+}
+
+/* disable the receiver; this must be called with the device spinlock held */
+static void it8708_disable_rx(struct ite_dev *dev)
+{
+ ite_dbg("%s called", __func__);
+
+ /* disable the receiver interrupts */
+ outb(inb(dev->cir_addr + IT8708_C0IER) &
+ ~(IT85_RDAIE | IT85_RFOIE),
+ dev->cir_addr + IT8708_C0IER);
+
+ /* disable the receiver */
+ outb(inb(dev->cir_addr + IT8708_C0RCR) & ~IT85_RXEN,
+ dev->cir_addr + IT8708_C0RCR);
+
+ /* clear the FIFO and RXACT (actually RXACT should have been cleared
+ * in the previous outb() call) */
+ it8708_idle_rx(dev);
+}
+
+/* enable the receiver; this must be called with the device spinlock held */
+static void it8708_enable_rx(struct ite_dev *dev)
+{
+ ite_dbg("%s called", __func__);
+
+ /* enable the receiver by setting RXEN */
+ outb(inb(dev->cir_addr + IT8708_C0RCR) | IT85_RXEN,
+ dev->cir_addr + IT8708_C0RCR);
+
+ /* just prepare it to idle for the next reception */
+ it8708_idle_rx(dev);
+
+ /* enable the receiver interrupts and master enable flag */
+ outb(inb(dev->cir_addr + IT8708_C0IER)
+ |IT85_RDAIE | IT85_RFOIE | IT85_IEC,
+ dev->cir_addr + IT8708_C0IER);
+}
+
+/* disable the transmitter interrupt; this must be called with the device
+ * spinlock held */
+static void it8708_disable_tx_interrupt(struct ite_dev *dev)
+{
+ ite_dbg("%s called", __func__);
+
+ /* disable the transmitter interrupts */
+ outb(inb(dev->cir_addr + IT8708_C0IER) & ~IT85_TLDLIE,
+ dev->cir_addr + IT8708_C0IER);
+}
+
+/* enable the transmitter interrupt; this must be called with the device
+ * spinlock held */
+static void it8708_enable_tx_interrupt(struct ite_dev *dev)
+{
+ ite_dbg("%s called", __func__);
+
+ /* enable the transmitter interrupts and master enable flag */
+ outb(inb(dev->cir_addr + IT8708_C0IER)
+ |IT85_TLDLIE | IT85_IEC,
+ dev->cir_addr + IT8708_C0IER);
+}
+
+/* disable the device; this must be called with the device spinlock held */
+static void it8708_disable(struct ite_dev *dev)
+{
+ ite_dbg("%s called", __func__);
+
+ /* clear out all interrupt enable flags */
+ outb(inb(dev->cir_addr + IT8708_C0IER) &
+ ~(IT85_IEC | IT85_RFOIE | IT85_RDAIE | IT85_TLDLIE),
+ dev->cir_addr + IT8708_C0IER);
+
+ /* disable the receiver */
+ it8708_disable_rx(dev);
+
+ /* erase the FIFO */
+ outb(IT85_FIFOCLR | inb(dev->cir_addr + IT8708_C0MSTCR),
+ dev->cir_addr + IT8708_C0MSTCR);
+}
+
+/* initialize the hardware */
+static void it8708_init_hardware(struct ite_dev *dev)
+{
+ ite_dbg("%s called", __func__);
+
+ /* disable all the interrupts */
+ outb(inb(dev->cir_addr + IT8708_C0IER) &
+ ~(IT85_IEC | IT85_RFOIE | IT85_RDAIE | IT85_TLDLIE),
+ dev->cir_addr + IT8708_C0IER);
+
+ /* program the baud rate divisor */
+ outb(inb(dev->cir_addr + IT8708_BANKSEL) | IT8708_HRAE,
+ dev->cir_addr + IT8708_BANKSEL);
+
+ outb(ITE_BAUDRATE_DIVISOR & 0xff, dev->cir_addr + IT8708_C0BDLR);
+ outb((ITE_BAUDRATE_DIVISOR >> 8) & 0xff,
+ dev->cir_addr + IT8708_C0BDHR);
+
+ outb(inb(dev->cir_addr + IT8708_BANKSEL) & ~IT8708_HRAE,
+ dev->cir_addr + IT8708_BANKSEL);
+
+ /* program the C0MSTCR register defaults */
+ outb((inb(dev->cir_addr + IT8708_C0MSTCR) &
+ ~(IT85_ILSEL | IT85_ILE | IT85_FIFOTL |
+ IT85_FIFOCLR | IT85_RESET)) |
+ IT85_FIFOTL_DEFAULT,
+ dev->cir_addr + IT8708_C0MSTCR);
+
+ /* program the C0RCR register defaults */
+ outb((inb(dev->cir_addr + IT8708_C0RCR) &
+ ~(IT85_RXEN | IT85_RDWOS | IT85_RXEND |
+ IT85_RXACT | IT85_RXDCR)) |
+ ITE_RXDCR_DEFAULT,
+ dev->cir_addr + IT8708_C0RCR);
+
+ /* program the C0TCR register defaults */
+ outb((inb(dev->cir_addr + IT8708_C0TCR) &
+ ~(IT85_TXMPM | IT85_TXMPW))
+ |IT85_TXRLE | IT85_TXENDF |
+ IT85_TXMPM_DEFAULT | IT85_TXMPW_DEFAULT,
+ dev->cir_addr + IT8708_C0TCR);
+
+ /* program the carrier parameters */
+ ite_set_carrier_params(dev);
+}
+
+/* IT8512F on ITE8709 HW-specific functions */
+
+/* read a byte from the SRAM module */
+static inline u8 it8709_rm(struct ite_dev *dev, int index)
+{
+ outb(index, dev->cir_addr + IT8709_RAM_IDX);
+ return inb(dev->cir_addr + IT8709_RAM_VAL);
+}
+
+/* write a byte to the SRAM module */
+static inline void it8709_wm(struct ite_dev *dev, u8 val, int index)
+{
+ outb(index, dev->cir_addr + IT8709_RAM_IDX);
+ outb(val, dev->cir_addr + IT8709_RAM_VAL);
+}
+
+static void it8709_wait(struct ite_dev *dev)
+{
+ int i = 0;
+ /*
+ * loop until device tells it's ready to continue
+ * iterations count is usually ~750 but can sometimes achieve 13000
+ */
+ for (i = 0; i < 15000; i++) {
+ udelay(2);
+ if (it8709_rm(dev, IT8709_MODE) == IT8709_IDLE)
+ break;
+ }
+}
+
+/* read the value of a CIR register */
+static u8 it8709_rr(struct ite_dev *dev, int index)
+{
+ /* just wait in case the previous access was a write */
+ it8709_wait(dev);
+ it8709_wm(dev, index, IT8709_REG_IDX);
+ it8709_wm(dev, IT8709_READ, IT8709_MODE);
+
+ /* wait for the read data to be available */
+ it8709_wait(dev);
+
+ /* return the read value */
+ return it8709_rm(dev, IT8709_REG_VAL);
+}
+
+/* write the value of a CIR register */
+static void it8709_wr(struct ite_dev *dev, u8 val, int index)
+{
+ /* we wait before writing, and not afterwards, since this allows us to
+ * pipeline the host CPU with the microcontroller */
+ it8709_wait(dev);
+ it8709_wm(dev, val, IT8709_REG_VAL);
+ it8709_wm(dev, index, IT8709_REG_IDX);
+ it8709_wm(dev, IT8709_WRITE, IT8709_MODE);
+}
+
+/* retrieve a bitmask of the current causes for a pending interrupt; this may
+ * be composed of ITE_IRQ_TX_FIFO, ITE_IRQ_RX_FIFO and ITE_IRQ_RX_FIFO_OVERRUN
+ * */
+static int it8709_get_irq_causes(struct ite_dev *dev)
+{
+ u8 iflags;
+ int ret = 0;
+
+ ite_dbg("%s called", __func__);
+
+ /* read the interrupt flags */
+ iflags = it8709_rm(dev, IT8709_IIR);
+
+ if (iflags & IT85_TLDLI)
+ ret |= ITE_IRQ_TX_FIFO;
+ if (iflags & IT85_RDAI)
+ ret |= ITE_IRQ_RX_FIFO;
+ if (iflags & IT85_RFOI)
+ ret |= ITE_IRQ_RX_FIFO_OVERRUN;
+
+ return ret;
+}
+
+/* set the carrier parameters; to be called with the spinlock held */
+static void it8709_set_carrier_params(struct ite_dev *dev, bool high_freq,
+ bool use_demodulator,
+ u8 carrier_freq_bits, u8 allowance_bits,
+ u8 pulse_width_bits)
+{
+ u8 val;
+
+ ite_dbg("%s called", __func__);
+
+ val = (it8709_rr(dev, IT85_C0CFR)
+ &~(IT85_HCFS | IT85_CFQ)) |
+ carrier_freq_bits;
+
+ if (high_freq)
+ val |= IT85_HCFS;
+
+ it8709_wr(dev, val, IT85_C0CFR);
+
+ /* program the C0RCR register */
+ val = it8709_rr(dev, IT85_C0RCR)
+ & ~(IT85_RXEND | IT85_RXDCR);
+
+ if (use_demodulator)
+ val |= IT85_RXEND;
+
+ val |= allowance_bits;
+
+ it8709_wr(dev, val, IT85_C0RCR);
+
+ /* program the C0TCR register */
+ val = it8709_rr(dev, IT85_C0TCR) & ~IT85_TXMPW;
+ val |= pulse_width_bits;
+ it8709_wr(dev, val, IT85_C0TCR);
+}
+
+/* read up to buf_size bytes from the RX FIFO; to be called with the spinlock
+ * held */
+static int it8709_get_rx_bytes(struct ite_dev *dev, u8 * buf, int buf_size)
+{
+ int fifo, read = 0;
+
+ ite_dbg("%s called", __func__);
+
+ /* read how many bytes are still in the FIFO */
+ fifo = it8709_rm(dev, IT8709_RFSR) & IT85_RXFBC;
+
+ while (fifo > 0 && buf_size > 0) {
+ *(buf++) = it8709_rm(dev, IT8709_FIFO + read);
+ fifo--;
+ read++;
+ buf_size--;
+ }
+
+ /* 'clear' the FIFO by setting the writing index to 0; this is
+ * completely bound to be racy, but we can't help it, since it's a
+ * limitation of the protocol */
+ it8709_wm(dev, 0, IT8709_RFSR);
+
+ return read;
+}
+
+/* return how many bytes are still in the FIFO; this will be called
+ * with the device spinlock NOT HELD while waiting for the TX FIFO to get
+ * empty; let's expect this won't be a problem */
+static int it8709_get_tx_used_slots(struct ite_dev *dev)
+{
+ ite_dbg("%s called", __func__);
+
+ return it8709_rr(dev, IT85_C0TFSR) & IT85_TXFBC;
+}
+
+/* put a byte to the TX fifo; this should be called with the spinlock held */
+static void it8709_put_tx_byte(struct ite_dev *dev, u8 value)
+{
+ it8709_wr(dev, value, IT85_C0DR);
+}
+
+/* idle the receiver so that we won't receive samples until another
+ pulse is detected; this must be called with the device spinlock held */
+static void it8709_idle_rx(struct ite_dev *dev)
+{
+ ite_dbg("%s called", __func__);
+
+ /* disable streaming by clearing RXACT writing it as 1 */
+ it8709_wr(dev, it8709_rr(dev, IT85_C0RCR) | IT85_RXACT,
+ IT85_C0RCR);
+
+ /* clear the FIFO */
+ it8709_wr(dev, it8709_rr(dev, IT85_C0MSTCR) | IT85_FIFOCLR,
+ IT85_C0MSTCR);
+}
+
+/* disable the receiver; this must be called with the device spinlock held */
+static void it8709_disable_rx(struct ite_dev *dev)
+{
+ ite_dbg("%s called", __func__);
+
+ /* disable the receiver interrupts */
+ it8709_wr(dev, it8709_rr(dev, IT85_C0IER) &
+ ~(IT85_RDAIE | IT85_RFOIE),
+ IT85_C0IER);
+
+ /* disable the receiver */
+ it8709_wr(dev, it8709_rr(dev, IT85_C0RCR) & ~IT85_RXEN,
+ IT85_C0RCR);
+
+ /* clear the FIFO and RXACT (actually RXACT should have been cleared
+ * in the previous it8709_wr(dev, ) call) */
+ it8709_idle_rx(dev);
+}
+
+/* enable the receiver; this must be called with the device spinlock held */
+static void it8709_enable_rx(struct ite_dev *dev)
+{
+ ite_dbg("%s called", __func__);
+
+ /* enable the receiver by setting RXEN */
+ it8709_wr(dev, it8709_rr(dev, IT85_C0RCR) | IT85_RXEN,
+ IT85_C0RCR);
+
+ /* just prepare it to idle for the next reception */
+ it8709_idle_rx(dev);
+
+ /* enable the receiver interrupts and master enable flag */
+ it8709_wr(dev, it8709_rr(dev, IT85_C0IER)
+ |IT85_RDAIE | IT85_RFOIE | IT85_IEC,
+ IT85_C0IER);
+}
+
+/* disable the transmitter interrupt; this must be called with the device
+ * spinlock held */
+static void it8709_disable_tx_interrupt(struct ite_dev *dev)
+{
+ ite_dbg("%s called", __func__);
+
+ /* disable the transmitter interrupts */
+ it8709_wr(dev, it8709_rr(dev, IT85_C0IER) & ~IT85_TLDLIE,
+ IT85_C0IER);
+}
+
+/* enable the transmitter interrupt; this must be called with the device
+ * spinlock held */
+static void it8709_enable_tx_interrupt(struct ite_dev *dev)
+{
+ ite_dbg("%s called", __func__);
+
+ /* enable the transmitter interrupts and master enable flag */
+ it8709_wr(dev, it8709_rr(dev, IT85_C0IER)
+ |IT85_TLDLIE | IT85_IEC,
+ IT85_C0IER);
+}
+
+/* disable the device; this must be called with the device spinlock held */
+static void it8709_disable(struct ite_dev *dev)
+{
+ ite_dbg("%s called", __func__);
+
+ /* clear out all interrupt enable flags */
+ it8709_wr(dev,
+ it8709_rr(dev,
+ IT85_C0IER) & ~(IT85_IEC | IT85_RFOIE |
+ IT85_RDAIE |
+ IT85_TLDLIE), IT85_C0IER);
+
+ /* disable the receiver */
+ it8709_disable_rx(dev);
+
+ /* erase the FIFO */
+ it8709_wr(dev, IT85_FIFOCLR | it8709_rr(dev, IT85_C0MSTCR),
+ IT85_C0MSTCR);
+}
+
+/* initialize the hardware */
+static void it8709_init_hardware(struct ite_dev *dev)
+{
+ ite_dbg("%s called", __func__);
+
+ /* disable all the interrupts */
+ it8709_wr(dev,
+ it8709_rr(dev,
+ IT85_C0IER) & ~(IT85_IEC | IT85_RFOIE |
+ IT85_RDAIE |
+ IT85_TLDLIE), IT85_C0IER);
+
+ /* program the baud rate divisor */
+ it8709_wr(dev, ITE_BAUDRATE_DIVISOR & 0xff, IT85_C0BDLR);
+ it8709_wr(dev, (ITE_BAUDRATE_DIVISOR >> 8) & 0xff,
+ IT85_C0BDHR);
+
+ /* program the C0MSTCR register defaults */
+ it8709_wr(dev, (it8709_rr(dev, IT85_C0MSTCR) & ~(IT85_ILSEL |
+ IT85_ILE
+ | IT85_FIFOTL
+ |
+ IT85_FIFOCLR
+ |
+ IT85_RESET))
+ | IT85_FIFOTL_DEFAULT, IT85_C0MSTCR);
+
+ /* program the C0RCR register defaults */
+ it8709_wr(dev,
+ (it8709_rr(dev, IT85_C0RCR) &
+ ~(IT85_RXEN | IT85_RDWOS | IT85_RXEND
+ | IT85_RXACT | IT85_RXDCR)) |
+ ITE_RXDCR_DEFAULT, IT85_C0RCR);
+
+ /* program the C0TCR register defaults */
+ it8709_wr(dev, (it8709_rr(dev, IT85_C0TCR)
+ &~(IT85_TXMPM | IT85_TXMPW))
+ |IT85_TXRLE | IT85_TXENDF |
+ IT85_TXMPM_DEFAULT |
+ IT85_TXMPW_DEFAULT, IT85_C0TCR);
+
+ /* program the carrier parameters */
+ ite_set_carrier_params(dev);
+}
+
+
+/* generic hardware setup/teardown code */
+
+/* activate the device for use */
+static int ite_open(struct rc_dev *rcdev)
+{
+ struct ite_dev *dev = rcdev->priv;
+ unsigned long flags;
+
+ ite_dbg("%s called", __func__);
+
+ spin_lock_irqsave(&dev->lock, flags);
+ dev->in_use = true;
+
+ /* enable the receiver */
+ dev->params.enable_rx(dev);
+
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ return 0;
+}
+
+/* deactivate the device for use */
+static void ite_close(struct rc_dev *rcdev)
+{
+ struct ite_dev *dev = rcdev->priv;
+ unsigned long flags;
+
+ ite_dbg("%s called", __func__);
+
+ spin_lock_irqsave(&dev->lock, flags);
+ dev->in_use = false;
+
+ /* wait for any transmission to end */
+ spin_unlock_irqrestore(&dev->lock, flags);
+ wait_event_interruptible(dev->tx_ended, !dev->transmitting);
+ spin_lock_irqsave(&dev->lock, flags);
+
+ dev->params.disable(dev);
+
+ spin_unlock_irqrestore(&dev->lock, flags);
+}
+
+/* supported models and their parameters */
+static const struct ite_dev_params ite_dev_descs[] = {
+ { /* 0: ITE8704 */
+ .model = "ITE8704 CIR transceiver",
+ .io_region_size = IT87_IOREG_LENGTH,
+ .hw_tx_capable = true,
+ .sample_period = (u32) (1000000000ULL / 115200),
+ .tx_carrier_freq = 38000,
+ .tx_duty_cycle = 33,
+ .rx_low_carrier_freq = 0,
+ .rx_high_carrier_freq = 0,
+
+ /* operations */
+ .get_irq_causes = it87_get_irq_causes,
+ .enable_rx = it87_enable_rx,
+ .idle_rx = it87_idle_rx,
+ .disable_rx = it87_idle_rx,
+ .get_rx_bytes = it87_get_rx_bytes,
+ .enable_tx_interrupt = it87_enable_tx_interrupt,
+ .disable_tx_interrupt = it87_disable_tx_interrupt,
+ .get_tx_used_slots = it87_get_tx_used_slots,
+ .put_tx_byte = it87_put_tx_byte,
+ .disable = it87_disable,
+ .init_hardware = it87_init_hardware,
+ .set_carrier_params = it87_set_carrier_params,
+ },
+ { /* 1: ITE8713 */
+ .model = "ITE8713 CIR transceiver",
+ .io_region_size = IT87_IOREG_LENGTH,
+ .hw_tx_capable = true,
+ .sample_period = (u32) (1000000000ULL / 115200),
+ .tx_carrier_freq = 38000,
+ .tx_duty_cycle = 33,
+ .rx_low_carrier_freq = 0,
+ .rx_high_carrier_freq = 0,
+
+ /* operations */
+ .get_irq_causes = it87_get_irq_causes,
+ .enable_rx = it87_enable_rx,
+ .idle_rx = it87_idle_rx,
+ .disable_rx = it87_idle_rx,
+ .get_rx_bytes = it87_get_rx_bytes,
+ .enable_tx_interrupt = it87_enable_tx_interrupt,
+ .disable_tx_interrupt = it87_disable_tx_interrupt,
+ .get_tx_used_slots = it87_get_tx_used_slots,
+ .put_tx_byte = it87_put_tx_byte,
+ .disable = it87_disable,
+ .init_hardware = it87_init_hardware,
+ .set_carrier_params = it87_set_carrier_params,
+ },
+ { /* 2: ITE8708 */
+ .model = "ITE8708 CIR transceiver",
+ .io_region_size = IT8708_IOREG_LENGTH,
+ .hw_tx_capable = true,
+ .sample_period = (u32) (1000000000ULL / 115200),
+ .tx_carrier_freq = 38000,
+ .tx_duty_cycle = 33,
+ .rx_low_carrier_freq = 0,
+ .rx_high_carrier_freq = 0,
+
+ /* operations */
+ .get_irq_causes = it8708_get_irq_causes,
+ .enable_rx = it8708_enable_rx,
+ .idle_rx = it8708_idle_rx,
+ .disable_rx = it8708_idle_rx,
+ .get_rx_bytes = it8708_get_rx_bytes,
+ .enable_tx_interrupt = it8708_enable_tx_interrupt,
+ .disable_tx_interrupt =
+ it8708_disable_tx_interrupt,
+ .get_tx_used_slots = it8708_get_tx_used_slots,
+ .put_tx_byte = it8708_put_tx_byte,
+ .disable = it8708_disable,
+ .init_hardware = it8708_init_hardware,
+ .set_carrier_params = it8708_set_carrier_params,
+ },
+ { /* 3: ITE8709 */
+ .model = "ITE8709 CIR transceiver",
+ .io_region_size = IT8709_IOREG_LENGTH,
+ .hw_tx_capable = true,
+ .sample_period = (u32) (1000000000ULL / 115200),
+ .tx_carrier_freq = 38000,
+ .tx_duty_cycle = 33,
+ .rx_low_carrier_freq = 0,
+ .rx_high_carrier_freq = 0,
+
+ /* operations */
+ .get_irq_causes = it8709_get_irq_causes,
+ .enable_rx = it8709_enable_rx,
+ .idle_rx = it8709_idle_rx,
+ .disable_rx = it8709_idle_rx,
+ .get_rx_bytes = it8709_get_rx_bytes,
+ .enable_tx_interrupt = it8709_enable_tx_interrupt,
+ .disable_tx_interrupt =
+ it8709_disable_tx_interrupt,
+ .get_tx_used_slots = it8709_get_tx_used_slots,
+ .put_tx_byte = it8709_put_tx_byte,
+ .disable = it8709_disable,
+ .init_hardware = it8709_init_hardware,
+ .set_carrier_params = it8709_set_carrier_params,
+ },
+};
+
+static const struct pnp_device_id ite_ids[] = {
+ {"ITE8704", 0}, /* Default model */
+ {"ITE8713", 1}, /* CIR found in EEEBox 1501U */
+ {"ITE8708", 2}, /* Bridged IT8512 */
+ {"ITE8709", 3}, /* SRAM-Bridged IT8512 */
+ {"", 0},
+};
+
+/* allocate memory, probe hardware, and initialize everything */
+static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
+ *dev_id)
+{
+ const struct ite_dev_params *dev_desc = NULL;
+ struct ite_dev *itdev = NULL;
+ struct rc_dev *rdev = NULL;
+ int ret = -ENOMEM;
+ int model_no;
+
+ ite_dbg("%s called", __func__);
+
+ itdev = kzalloc(sizeof(struct ite_dev), GFP_KERNEL);
+ if (!itdev)
+ return ret;
+
+ /* input device for IR remote (and tx) */
+ rdev = rc_allocate_device();
+ if (!rdev)
+ goto failure;
+
+ ret = -ENODEV;
+
+ /* get the model number */
+ model_no = (int)dev_id->driver_data;
+ ite_pr(KERN_NOTICE, "Auto-detected model: %s\n",
+ ite_dev_descs[model_no].model);
+
+ if (model_number >= 0 && model_number < ARRAY_SIZE(ite_dev_descs)) {
+ model_no = model_number;
+ ite_pr(KERN_NOTICE, "The model has been fixed by a module "
+ "parameter.");
+ }
+
+ ite_pr(KERN_NOTICE, "Using model: %s\n", ite_dev_descs[model_no].model);
+
+ /* get the description for the device */
+ dev_desc = &ite_dev_descs[model_no];
+
+ /* validate pnp resources */
+ if (!pnp_port_valid(pdev, 0) ||
+ pnp_port_len(pdev, 0) != dev_desc->io_region_size) {
+ dev_err(&pdev->dev, "IR PNP Port not valid!\n");
+ goto failure;
+ }
+
+ if (!pnp_irq_valid(pdev, 0)) {
+ dev_err(&pdev->dev, "PNP IRQ not valid!\n");
+ goto failure;
+ }
+
+ /* store resource values */
+ itdev->cir_addr = pnp_port_start(pdev, 0);
+ itdev->cir_irq =pnp_irq(pdev, 0);
+
+ /* initialize spinlocks */
+ spin_lock_init(&itdev->lock);
+
+ /* initialize raw event */
+ init_ir_raw_event(&itdev->rawir);
+
+ ret = -EBUSY;
+ /* now claim resources */
+ if (!request_region(itdev->cir_addr,
+ dev_desc->io_region_size, ITE_DRIVER_NAME))
+ goto failure;
+
+ if (request_irq(itdev->cir_irq, ite_cir_isr, IRQF_SHARED,
+ ITE_DRIVER_NAME, (void *)itdev))
+ goto failure;
+
+ /* set driver data into the pnp device */
+ pnp_set_drvdata(pdev, itdev);
+ itdev->pdev = pdev;
+
+ /* initialize waitqueues for transmission */
+ init_waitqueue_head(&itdev->tx_queue);
+ init_waitqueue_head(&itdev->tx_ended);
+
+ /* copy model-specific parameters */
+ itdev->params = *dev_desc;
+
+ /* apply any overrides */
+ if (sample_period > 0)
+ itdev->params.sample_period = sample_period;
+
+ if (tx_carrier_freq > 0)
+ itdev->params.tx_carrier_freq = tx_carrier_freq;
+
+ if (tx_duty_cycle > 0 && tx_duty_cycle <= 100)
+ itdev->params.tx_duty_cycle = tx_duty_cycle;
+
+ if (rx_low_carrier_freq > 0)
+ itdev->params.rx_low_carrier_freq = rx_low_carrier_freq;
+
+ if (rx_high_carrier_freq > 0)
+ itdev->params.rx_high_carrier_freq = rx_high_carrier_freq;
+
+ /* print out parameters */
+ ite_pr(KERN_NOTICE, "TX-capable: %d\n", (int)
+ itdev->params.hw_tx_capable);
+ ite_pr(KERN_NOTICE, "Sample period (ns): %ld\n", (long)
+ itdev->params.sample_period);
+ ite_pr(KERN_NOTICE, "TX carrier frequency (Hz): %d\n", (int)
+ itdev->params.tx_carrier_freq);
+ ite_pr(KERN_NOTICE, "TX duty cycle (%%): %d\n", (int)
+ itdev->params.tx_duty_cycle);
+ ite_pr(KERN_NOTICE, "RX low carrier frequency (Hz): %d\n", (int)
+ itdev->params.rx_low_carrier_freq);
+ ite_pr(KERN_NOTICE, "RX high carrier frequency (Hz): %d\n", (int)
+ itdev->params.rx_high_carrier_freq);
+
+ /* set up hardware initial state */
+ itdev->params.init_hardware(itdev);
+
+ /* set up ir-core props */
+ rdev->priv = itdev;
+ rdev->driver_type = RC_DRIVER_IR_RAW;
+ rdev->allowed_protos = RC_TYPE_ALL;
+ rdev->open = ite_open;
+ rdev->close = ite_close;
+ rdev->s_idle = ite_s_idle;
+ rdev->s_rx_carrier_range = ite_set_rx_carrier_range;
+ rdev->min_timeout = ITE_MIN_IDLE_TIMEOUT;
+ rdev->max_timeout = ITE_MAX_IDLE_TIMEOUT;
+ rdev->timeout = ITE_IDLE_TIMEOUT;
+ rdev->rx_resolution = ITE_BAUDRATE_DIVISOR *
+ itdev->params.sample_period;
+ rdev->tx_resolution = ITE_BAUDRATE_DIVISOR *
+ itdev->params.sample_period;
+
+ /* set up transmitter related values if needed */
+ if (itdev->params.hw_tx_capable) {
+ rdev->tx_ir = ite_tx_ir;
+ rdev->s_tx_carrier = ite_set_tx_carrier;
+ rdev->s_tx_duty_cycle = ite_set_tx_duty_cycle;
+ }
+
+ rdev->input_name = dev_desc->model;
+ rdev->input_id.bustype = BUS_HOST;
+ rdev->input_id.vendor = PCI_VENDOR_ID_ITE;
+ rdev->input_id.product = 0;
+ rdev->input_id.version = 0;
+ rdev->driver_name = ITE_DRIVER_NAME;
+ rdev->map_name = RC_MAP_RC6_MCE;
+
+ ret = rc_register_device(rdev);
+ if (ret)
+ goto failure;
+
+ itdev->rdev = rdev;
+ ite_pr(KERN_NOTICE, "driver has been successfully loaded\n");
+
+ return 0;
+
+failure:
+ if (itdev->cir_irq)
+ free_irq(itdev->cir_irq, itdev);
+
+ if (itdev->cir_addr)
+ release_region(itdev->cir_addr, itdev->params.io_region_size);
+
+ rc_free_device(rdev);
+ kfree(itdev);
+
+ return ret;
+}
+
+static void __devexit ite_remove(struct pnp_dev *pdev)
+{
+ struct ite_dev *dev = pnp_get_drvdata(pdev);
+ unsigned long flags;
+
+ ite_dbg("%s called", __func__);
+
+ spin_lock_irqsave(&dev->lock, flags);
+
+ /* disable hardware */
+ dev->params.disable(dev);
+
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ /* free resources */
+ free_irq(dev->cir_irq, dev);
+ release_region(dev->cir_addr, dev->params.io_region_size);
+
+ rc_unregister_device(dev->rdev);
+
+ kfree(dev);
+}
+
+static int ite_suspend(struct pnp_dev *pdev, pm_message_t state)
+{
+ struct ite_dev *dev = pnp_get_drvdata(pdev);
+ unsigned long flags;
+
+ ite_dbg("%s called", __func__);
+
+ spin_lock_irqsave(&dev->lock, flags);
+
+ /* disable all interrupts */
+ dev->params.disable(dev);
+
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ return 0;
+}
+
+static int ite_resume(struct pnp_dev *pdev)
+{
+ int ret = 0;
+ struct ite_dev *dev = pnp_get_drvdata(pdev);
+ unsigned long flags;
+
+ ite_dbg("%s called", __func__);
+
+ spin_lock_irqsave(&dev->lock, flags);
+
+ if (dev->transmitting) {
+ /* wake up the transmitter */
+ wake_up_interruptible(&dev->tx_queue);
+ } else {
+ /* enable the receiver */
+ dev->params.enable_rx(dev);
+ }
+
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ return ret;
+}
+
+static void ite_shutdown(struct pnp_dev *pdev)
+{
+ struct ite_dev *dev = pnp_get_drvdata(pdev);
+ unsigned long flags;
+
+ ite_dbg("%s called", __func__);
+
+ spin_lock_irqsave(&dev->lock, flags);
+
+ /* disable all interrupts */
+ dev->params.disable(dev);
+
+ spin_unlock_irqrestore(&dev->lock, flags);
+}
+
+static struct pnp_driver ite_driver = {
+ .name = ITE_DRIVER_NAME,
+ .id_table = ite_ids,
+ .probe = ite_probe,
+ .remove = __devexit_p(ite_remove),
+ .suspend = ite_suspend,
+ .resume = ite_resume,
+ .shutdown = ite_shutdown,
+};
+
+int ite_init(void)
+{
+ return pnp_register_driver(&ite_driver);
+}
+
+void ite_exit(void)
+{
+ pnp_unregister_driver(&ite_driver);
+}
+
+MODULE_DEVICE_TABLE(pnp, ite_ids);
+MODULE_DESCRIPTION("ITE Tech Inc. IT8712F/ITE8512F CIR driver");
+
+MODULE_AUTHOR("Juan J. Garcia de Soria <skandalfo@gmail.com>");
+MODULE_LICENSE("GPL");
+
+module_init(ite_init);
+module_exit(ite_exit);
diff --git a/drivers/media/rc/ite-cir.h b/drivers/media/rc/ite-cir.h
new file mode 100644
index 0000000..996bb06
--- /dev/null
+++ b/drivers/media/rc/ite-cir.h
@@ -0,0 +1,478 @@
+/*
+ * Driver for ITE Tech Inc. IT8712F/IT8512F CIR
+ *
+ * Copyright (C) 2010 Juan Jesús García de Soria <skandalfo@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.
+ */
+
+/* platform driver name to register */
+#define ITE_DRIVER_NAME "ite-cir"
+
+/* logging macros */
+#define ite_pr(level, text, ...) \
+ printk(level KBUILD_MODNAME ": " text, ## __VA_ARGS__)
+#define ite_dbg(text, ...) \
+ if (debug) \
+ printk(KERN_DEBUG \
+ KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__)
+#define ite_dbg_verbose(text, ...) \
+ if (debug > 1) \
+ printk(KERN_DEBUG \
+ KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__)
+
+/* FIFO sizes */
+#define ITE_TX_FIFO_LEN 32
+#define ITE_RX_FIFO_LEN 32
+
+/* interrupt types */
+#define ITE_IRQ_TX_FIFO 1
+#define ITE_IRQ_RX_FIFO 2
+#define ITE_IRQ_RX_FIFO_OVERRUN 4
+
+/* forward declaration */
+struct ite_dev;
+
+/* struct for storing the parameters of different recognized devices */
+struct ite_dev_params {
+ /* model of the device */
+ const char *model;
+
+ /* size of the I/O region */
+ int io_region_size;
+
+ /* true if the hardware supports transmission */
+ bool hw_tx_capable;
+
+ /* base sampling period, in ns */
+ u32 sample_period;
+
+ /* rx low carrier frequency, in Hz, 0 means no demodulation */
+ unsigned int rx_low_carrier_freq;
+
+ /* tx high carrier frequency, in Hz, 0 means no demodulation */
+ unsigned int rx_high_carrier_freq;
+
+ /* tx carrier frequency, in Hz */
+ unsigned int tx_carrier_freq;
+
+ /* duty cycle, 0-100 */
+ int tx_duty_cycle;
+
+ /* hw-specific operation function pointers; most of these must be
+ * called while holding the spin lock, except for the TX FIFO length
+ * one */
+ /* get pending interrupt causes */
+ int (*get_irq_causes) (struct ite_dev * dev);
+
+ /* enable rx */
+ void (*enable_rx) (struct ite_dev * dev);
+
+ /* make rx enter the idle state; keep listening for a pulse, but stop
+ * streaming space bytes */
+ void (*idle_rx) (struct ite_dev * dev);
+
+ /* disable rx completely */
+ void (*disable_rx) (struct ite_dev * dev);
+
+ /* read bytes from RX FIFO; return read count */
+ int (*get_rx_bytes) (struct ite_dev * dev, u8 * buf, int buf_size);
+
+ /* enable tx FIFO space available interrupt */
+ void (*enable_tx_interrupt) (struct ite_dev * dev);
+
+ /* disable tx FIFO space available interrupt */
+ void (*disable_tx_interrupt) (struct ite_dev * dev);
+
+ /* get number of full TX FIFO slots */
+ int (*get_tx_used_slots) (struct ite_dev * dev);
+
+ /* put a byte to the TX FIFO */
+ void (*put_tx_byte) (struct ite_dev * dev, u8 value);
+
+ /* disable hardware completely */
+ void (*disable) (struct ite_dev * dev);
+
+ /* initialize the hardware */
+ void (*init_hardware) (struct ite_dev * dev);
+
+ /* set the carrier parameters */
+ void (*set_carrier_params) (struct ite_dev * dev, bool high_freq,
+ bool use_demodulator, u8 carrier_freq_bits,
+ u8 allowance_bits, u8 pulse_width_bits);
+};
+
+/* ITE CIR device structure */
+struct ite_dev {
+ struct pnp_dev *pdev;
+ struct rc_dev *rdev;
+ struct ir_raw_event rawir;
+
+ /* sync data */
+ spinlock_t lock;
+ bool in_use, transmitting;
+
+ /* transmit support */
+ int tx_fifo_allowance;
+ wait_queue_head_t tx_queue, tx_ended;
+
+ /* hardware I/O settings */
+ unsigned long cir_addr;
+ int cir_irq;
+
+ /* overridable copy of model parameters */
+ struct ite_dev_params params;
+};
+
+/* common values for all kinds of hardware */
+
+/* baud rate divisor default */
+#define ITE_BAUDRATE_DIVISOR 1
+
+/* low-speed carrier frequency limits (Hz) */
+#define ITE_LCF_MIN_CARRIER_FREQ 27000
+#define ITE_LCF_MAX_CARRIER_FREQ 58000
+
+/* high-speed carrier frequency limits (Hz) */
+#define ITE_HCF_MIN_CARRIER_FREQ 400000
+#define ITE_HCF_MAX_CARRIER_FREQ 500000
+
+/* default carrier freq for when demodulator is off (Hz) */
+#define ITE_DEFAULT_CARRIER_FREQ 38000
+
+/* default idling timeout in ns (0.2 seconds) */
+#define ITE_IDLE_TIMEOUT 200000000UL
+
+/* limit timeout values */
+#define ITE_MIN_IDLE_TIMEOUT 100000000UL
+#define ITE_MAX_IDLE_TIMEOUT 1000000000UL
+
+/* convert bits to us */
+#define ITE_BITS_TO_NS(bits, sample_period) \
+((u32) ((bits) * ITE_BAUDRATE_DIVISOR * sample_period))
+
+/*
+ * n in RDCR produces a tolerance of +/- n * 6.25% around the center
+ * carrier frequency...
+ *
+ * From two limit frequencies, L (low) and H (high), we can get both the
+ * center frequency F = (L + H) / 2 and the variation from the center
+ * frequency A = (H - L) / (H + L). We can use this in order to honor the
+ * s_rx_carrier_range() call in ir-core. We'll suppose that any request
+ * setting L=0 means we must shut down the demodulator.
+ */
+#define ITE_RXDCR_PER_10000_STEP 625
+
+/* high speed carrier freq values */
+#define ITE_CFQ_400 0x03
+#define ITE_CFQ_450 0x08
+#define ITE_CFQ_480 0x0b
+#define ITE_CFQ_500 0x0d
+
+/* values for pulse widths */
+#define ITE_TXMPW_A 0x02
+#define ITE_TXMPW_B 0x03
+#define ITE_TXMPW_C 0x04
+#define ITE_TXMPW_D 0x05
+#define ITE_TXMPW_E 0x06
+
+/* values for demodulator carrier range allowance */
+#define ITE_RXDCR_DEFAULT 0x01 /* default carrier range */
+#define ITE_RXDCR_MAX 0x07 /* default carrier range */
+
+/* DR TX bits */
+#define ITE_TX_PULSE 0x00
+#define ITE_TX_SPACE 0x80
+#define ITE_TX_MAX_RLE 0x80
+#define ITE_TX_RLE_MASK 0x7f
+
+/*
+ * IT8712F
+ *
+ * hardware data obtained from:
+ *
+ * IT8712F
+ * Environment Control Low Pin Count Input / Output
+ * (EC - LPC I/O)
+ * Preliminary Specification V0. 81
+ */
+
+/* register offsets */
+#define IT87_DR 0x00 /* data register */
+#define IT87_IER 0x01 /* interrupt enable register */
+#define IT87_RCR 0x02 /* receiver control register */
+#define IT87_TCR1 0x03 /* transmitter control register 1 */
+#define IT87_TCR2 0x04 /* transmitter control register 2 */
+#define IT87_TSR 0x05 /* transmitter status register */
+#define IT87_RSR 0x06 /* receiver status register */
+#define IT87_BDLR 0x05 /* baud rate divisor low byte register */
+#define IT87_BDHR 0x06 /* baud rate divisor high byte register */
+#define IT87_IIR 0x07 /* interrupt identification register */
+
+#define IT87_IOREG_LENGTH 0x08 /* length of register file */
+
+/* IER bits */
+#define IT87_TLDLIE 0x01 /* transmitter low data interrupt enable */
+#define IT87_RDAIE 0x02 /* receiver data available interrupt enable */
+#define IT87_RFOIE 0x04 /* receiver FIFO overrun interrupt enable */
+#define IT87_IEC 0x08 /* interrupt enable control */
+#define IT87_BR 0x10 /* baud rate register enable */
+#define IT87_RESET 0x20 /* reset */
+
+/* RCR bits */
+#define IT87_RXDCR 0x07 /* receiver demodulation carrier range mask */
+#define IT87_RXACT 0x08 /* receiver active */
+#define IT87_RXEND 0x10 /* receiver demodulation enable */
+#define IT87_RXEN 0x20 /* receiver enable */
+#define IT87_HCFS 0x40 /* high-speed carrier frequency select */
+#define IT87_RDWOS 0x80 /* receiver data without sync */
+
+/* TCR1 bits */
+#define IT87_TXMPM 0x03 /* transmitter modulation pulse mode mask */
+#define IT87_TXMPM_DEFAULT 0x00 /* modulation pulse mode default */
+#define IT87_TXENDF 0x04 /* transmitter deferral */
+#define IT87_TXRLE 0x08 /* transmitter run length enable */
+#define IT87_FIFOTL 0x30 /* FIFO level threshold mask */
+#define IT87_FIFOTL_DEFAULT 0x20 /* FIFO level threshold default
+ * 0x00 -> 1, 0x10 -> 7, 0x20 -> 17,
+ * 0x30 -> 25 */
+#define IT87_ILE 0x40 /* internal loopback enable */
+#define IT87_FIFOCLR 0x80 /* FIFO clear bit */
+
+/* TCR2 bits */
+#define IT87_TXMPW 0x07 /* transmitter modulation pulse width mask */
+#define IT87_TXMPW_DEFAULT 0x04 /* default modulation pulse width */
+#define IT87_CFQ 0xf8 /* carrier frequency mask */
+#define IT87_CFQ_SHIFT 3 /* carrier frequency bit shift */
+
+/* TSR bits */
+#define IT87_TXFBC 0x3f /* transmitter FIFO byte count mask */
+
+/* RSR bits */
+#define IT87_RXFBC 0x3f /* receiver FIFO byte count mask */
+#define IT87_RXFTO 0x80 /* receiver FIFO time-out */
+
+/* IIR bits */
+#define IT87_IP 0x01 /* interrupt pending */
+#define IT87_II 0x06 /* interrupt identification mask */
+#define IT87_II_NOINT 0x00 /* no interrupt */
+#define IT87_II_TXLDL 0x02 /* transmitter low data level */
+#define IT87_II_RXDS 0x04 /* receiver data stored */
+#define IT87_II_RXFO 0x06 /* receiver FIFO overrun */
+
+/*
+ * IT8512E/F
+ *
+ * Hardware data obtained from:
+ *
+ * IT8512E/F
+ * Embedded Controller
+ * Preliminary Specification V0.4.1
+ *
+ * Note that the CIR registers are not directly available to the host, because
+ * they only are accessible to the integrated microcontroller. Thus, in order
+ * use it, some kind of bridging is required. As the bridging may depend on
+ * the controller firmware in use, we are going to use the PNP ID in order to
+ * determine the strategy and ports available. See after these generic
+ * IT8512E/F register definitions for register definitions for those
+ * strategies.
+ */
+
+/* register offsets */
+#define IT85_C0DR 0x00 /* data register */
+#define IT85_C0MSTCR 0x01 /* master control register */
+#define IT85_C0IER 0x02 /* interrupt enable register */
+#define IT85_C0IIR 0x03 /* interrupt identification register */
+#define IT85_C0CFR 0x04 /* carrier frequency register */
+#define IT85_C0RCR 0x05 /* receiver control register */
+#define IT85_C0TCR 0x06 /* transmitter control register */
+#define IT85_C0SCK 0x07 /* slow clock control register */
+#define IT85_C0BDLR 0x08 /* baud rate divisor low byte register */
+#define IT85_C0BDHR 0x09 /* baud rate divisor high byte register */
+#define IT85_C0TFSR 0x0a /* transmitter FIFO status register */
+#define IT85_C0RFSR 0x0b /* receiver FIFO status register */
+#define IT85_C0WCL 0x0d /* wakeup code length register */
+#define IT85_C0WCR 0x0e /* wakeup code read/write register */
+#define IT85_C0WPS 0x0f /* wakeup power control/status register */
+
+#define IT85_IOREG_LENGTH 0x10 /* length of register file */
+
+/* C0MSTCR bits */
+#define IT85_RESET 0x01 /* reset */
+#define IT85_FIFOCLR 0x02 /* FIFO clear bit */
+#define IT85_FIFOTL 0x0c /* FIFO level threshold mask */
+#define IT85_FIFOTL_DEFAULT 0x08 /* FIFO level threshold default
+ * 0x00 -> 1, 0x04 -> 7, 0x08 -> 17,
+ * 0x0c -> 25 */
+#define IT85_ILE 0x10 /* internal loopback enable */
+#define IT85_ILSEL 0x20 /* internal loopback select */
+
+/* C0IER bits */
+#define IT85_TLDLIE 0x01 /* TX low data level interrupt enable */
+#define IT85_RDAIE 0x02 /* RX data available interrupt enable */
+#define IT85_RFOIE 0x04 /* RX FIFO overrun interrupt enable */
+#define IT85_IEC 0x80 /* interrupt enable function control */
+
+/* C0IIR bits */
+#define IT85_TLDLI 0x01 /* transmitter low data level interrupt */
+#define IT85_RDAI 0x02 /* receiver data available interrupt */
+#define IT85_RFOI 0x04 /* receiver FIFO overrun interrupt */
+#define IT85_NIP 0x80 /* no interrupt pending */
+
+/* C0CFR bits */
+#define IT85_CFQ 0x1f /* carrier frequency mask */
+#define IT85_HCFS 0x20 /* high speed carrier frequency select */
+
+/* C0RCR bits */
+#define IT85_RXDCR 0x07 /* receiver demodulation carrier range mask */
+#define IT85_RXACT 0x08 /* receiver active */
+#define IT85_RXEND 0x10 /* receiver demodulation enable */
+#define IT85_RDWOS 0x20 /* receiver data without sync */
+#define IT85_RXEN 0x80 /* receiver enable */
+
+/* C0TCR bits */
+#define IT85_TXMPW 0x07 /* transmitter modulation pulse width mask */
+#define IT85_TXMPW_DEFAULT 0x04 /* default modulation pulse width */
+#define IT85_TXMPM 0x18 /* transmitter modulation pulse mode mask */
+#define IT85_TXMPM_DEFAULT 0x00 /* modulation pulse mode default */
+#define IT85_TXENDF 0x20 /* transmitter deferral */
+#define IT85_TXRLE 0x40 /* transmitter run length enable */
+
+/* C0SCK bits */
+#define IT85_SCKS 0x01 /* slow clock select */
+#define IT85_TXDCKG 0x02 /* TXD clock gating */
+#define IT85_DLL1P8E 0x04 /* DLL 1.8432M enable */
+#define IT85_DLLTE 0x08 /* DLL test enable */
+#define IT85_BRCM 0x70 /* baud rate count mode */
+#define IT85_DLLOCK 0x80 /* DLL lock */
+
+/* C0TFSR bits */
+#define IT85_TXFBC 0x3f /* transmitter FIFO count mask */
+
+/* C0RFSR bits */
+#define IT85_RXFBC 0x3f /* receiver FIFO count mask */
+#define IT85_RXFTO 0x80 /* receiver FIFO time-out */
+
+/* C0WCL bits */
+#define IT85_WCL 0x3f /* wakeup code length mask */
+
+/* C0WPS bits */
+#define IT85_CIRPOSIE 0x01 /* power on/off status interrupt enable */
+#define IT85_CIRPOIS 0x02 /* power on/off interrupt status */
+#define IT85_CIRPOII 0x04 /* power on/off interrupt identification */
+#define IT85_RCRST 0x10 /* wakeup code reading counter reset bit */
+#define IT85_WCRST 0x20 /* wakeup code writing counter reset bit */
+
+/*
+ * ITE8708
+ *
+ * Hardware data obtained from hacked driver for IT8512 in this forum post:
+ *
+ * http://ubuntuforums.org/showthread.php?t=1028640
+ *
+ * Although there's no official documentation for that driver, analysis would
+ * suggest that it maps the 16 registers of IT8512 onto two 8-register banks,
+ * selectable by a single bank-select bit that's mapped onto both banks. The
+ * IT8512 registers are mapped in a different order, so that the first bank
+ * maps the ones that are used more often, and two registers that share a
+ * reserved high-order bit are placed at the same offset in both banks in
+ * order to reuse the reserved bit as the bank select bit.
+ */
+
+/* register offsets */
+
+/* mapped onto both banks */
+#define IT8708_BANKSEL 0x07 /* bank select register */
+#define IT8708_HRAE 0x80 /* high registers access enable */
+
+/* mapped onto the low bank */
+#define IT8708_C0DR 0x00 /* data register */
+#define IT8708_C0MSTCR 0x01 /* master control register */
+#define IT8708_C0IER 0x02 /* interrupt enable register */
+#define IT8708_C0IIR 0x03 /* interrupt identification register */
+#define IT8708_C0RFSR 0x04 /* receiver FIFO status register */
+#define IT8708_C0RCR 0x05 /* receiver control register */
+#define IT8708_C0TFSR 0x06 /* transmitter FIFO status register */
+#define IT8708_C0TCR 0x07 /* transmitter control register */
+
+/* mapped onto the high bank */
+#define IT8708_C0BDLR 0x01 /* baud rate divisor low byte register */
+#define IT8708_C0BDHR 0x02 /* baud rate divisor high byte register */
+#define IT8708_C0CFR 0x04 /* carrier frequency register */
+
+/* registers whose bank mapping we don't know, since they weren't being used
+ * in the hacked driver... most probably they belong to the high bank too,
+ * since they fit in the holes the other registers leave */
+#define IT8708_C0SCK 0x03 /* slow clock control register */
+#define IT8708_C0WCL 0x05 /* wakeup code length register */
+#define IT8708_C0WCR 0x06 /* wakeup code read/write register */
+#define IT8708_C0WPS 0x07 /* wakeup power control/status register */
+
+#define IT8708_IOREG_LENGTH 0x08 /* length of register file */
+
+/* two more registers that are defined in the hacked driver, but can't be
+ * found in the data sheets; no idea what they are or how they are accessed,
+ * since the hacked driver doesn't seem to use them */
+#define IT8708_CSCRR 0x00
+#define IT8708_CGPINTR 0x01
+
+/* CSCRR bits */
+#define IT8708_CSCRR_SCRB 0x3f
+#define IT8708_CSCRR_PM 0x80
+
+/* CGPINTR bits */
+#define IT8708_CGPINT 0x01
+
+/*
+ * ITE8709
+ *
+ * Hardware interfacing data obtained from the original lirc_ite8709 driver.
+ * Verbatim from its sources:
+ *
+ * The ITE8709 device seems to be the combination of IT8512 superIO chip and
+ * a specific firmware running on the IT8512's embedded micro-controller.
+ * In addition of the embedded micro-controller, the IT8512 chip contains a
+ * CIR module and several other modules. A few modules are directly accessible
+ * by the host CPU, but most of them are only accessible by the
+ * micro-controller. The CIR module is only accessible by the
+ * micro-controller.
+ *
+ * The battery-backed SRAM module is accessible by the host CPU and the
+ * micro-controller. So one of the MC's firmware role is to act as a bridge
+ * between the host CPU and the CIR module. The firmware implements a kind of
+ * communication protocol using the SRAM module as a shared memory. The IT8512
+ * specification is publicly available on ITE's web site, but the
+ * communication protocol is not, so it was reverse-engineered.
+ */
+
+/* register offsets */
+#define IT8709_RAM_IDX 0x00 /* index into the SRAM module bytes */
+#define IT8709_RAM_VAL 0x01 /* read/write data to the indexed byte */
+
+#define IT8709_IOREG_LENGTH 0x02 /* length of register file */
+
+/* register offsets inside the SRAM module */
+#define IT8709_MODE 0x1a /* request/ack byte */
+#define IT8709_REG_IDX 0x1b /* index of the CIR register to access */
+#define IT8709_REG_VAL 0x1c /* value read/to be written */
+#define IT8709_IIR 0x1e /* interrupt identification register */
+#define IT8709_RFSR 0x1f /* receiver FIFO status register */
+#define IT8709_FIFO 0x20 /* start of in RAM RX FIFO copy */
+
+/* MODE values */
+#define IT8709_IDLE 0x00
+#define IT8709_WRITE 0x01
+#define IT8709_READ 0x02
diff --git a/drivers/staging/lirc/Kconfig b/drivers/staging/lirc/Kconfig
index cdaff59..526ec0f 100644
--- a/drivers/staging/lirc/Kconfig
+++ b/drivers/staging/lirc/Kconfig
@@ -32,18 +32,6 @@ config LIRC_IMON
Current generation iMON devices use the input layer imon driver.
-config LIRC_IT87
- tristate "ITE IT87XX CIR Port Receiver"
- depends on LIRC && PNP
- help
- Driver for the ITE IT87xx IR Receiver
-
-config LIRC_ITE8709
- tristate "ITE8709 CIR Port Receiver"
- depends on LIRC && PNP
- help
- Driver for the ITE8709 IR Receiver
-
config LIRC_PARALLEL
tristate "Homebrew Parallel Port Receiver"
depends on LIRC && PARPORT
diff --git a/drivers/staging/lirc/Makefile b/drivers/staging/lirc/Makefile
index 94af218..d76b0fa 100644
--- a/drivers/staging/lirc/Makefile
+++ b/drivers/staging/lirc/Makefile
@@ -6,8 +6,6 @@
obj-$(CONFIG_LIRC_BT829) += lirc_bt829.o
obj-$(CONFIG_LIRC_IGORPLUGUSB) += lirc_igorplugusb.o
obj-$(CONFIG_LIRC_IMON) += lirc_imon.o
-obj-$(CONFIG_LIRC_IT87) += lirc_it87.o
-obj-$(CONFIG_LIRC_ITE8709) += lirc_ite8709.o
obj-$(CONFIG_LIRC_PARALLEL) += lirc_parallel.o
obj-$(CONFIG_LIRC_SASEM) += lirc_sasem.o
obj-$(CONFIG_LIRC_SERIAL) += lirc_serial.o
diff --git a/drivers/staging/lirc/lirc_it87.c b/drivers/staging/lirc/lirc_it87.c
deleted file mode 100644
index 5938616..0000000
--- a/drivers/staging/lirc/lirc_it87.c
+++ /dev/null
@@ -1,1027 +0,0 @@
-/*
- * LIRC driver for ITE IT8712/IT8705 CIR port
- *
- * Copyright (C) 2001 Hans-Gunter Lutke Uphues <hg_lu@web.de>
- *
- * 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
- *
- * ITE IT8705 and IT8712(not tested) and IT8720 CIR-port support for lirc based
- * via cut and paste from lirc_sir.c (C) 2000 Milan Pikula
- *
- * Attention: Sendmode only tested with debugging logs
- *
- * 2001/02/27 Christoph Bartelmus <lirc@bartelmus.de> :
- * reimplemented read function
- * 2005/06/05 Andrew Calkin implemented support for Asus Digimatrix,
- * based on work of the following member of the Outertrack Digimatrix
- * Forum: Art103 <r_tay@hotmail.com>
- * 2009/12/24 James Edwards <jimbo-lirc@edwardsclan.net> implemeted support
- * for ITE8704/ITE8718, on my machine, the DSDT reports 8704, but the
- * chip identifies as 18.
- */
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/fs.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/time.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/wait.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/poll.h>
-#include <asm/system.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/fcntl.h>
-
-#include <linux/timer.h>
-#include <linux/pnp.h>
-
-#include <media/lirc.h>
-#include <media/lirc_dev.h>
-
-#include "lirc_it87.h"
-
-#ifdef LIRC_IT87_DIGIMATRIX
-static int digimatrix = 1;
-static int it87_freq = 36; /* kHz */
-static int irq = 9;
-#else
-static int digimatrix;
-static int it87_freq = 38; /* kHz */
-static int irq = IT87_CIR_DEFAULT_IRQ;
-#endif
-
-static unsigned long it87_bits_in_byte_out;
-static unsigned long it87_send_counter;
-static unsigned char it87_RXEN_mask = IT87_CIR_RCR_RXEN;
-
-#define RBUF_LEN 1024
-
-#define LIRC_DRIVER_NAME "lirc_it87"
-
-/* timeout for sequences in jiffies (=5/100s) */
-/* must be longer than TIME_CONST */
-#define IT87_TIMEOUT (HZ*5/100)
-
-/* module parameters */
-static int debug;
-#define dprintk(fmt, args...) \
- do { \
- if (debug) \
- printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \
- fmt, ## args); \
- } while (0)
-
-static int io = IT87_CIR_DEFAULT_IOBASE;
-/* receiver demodulator default: off */
-static int it87_enable_demodulator;
-
-static int timer_enabled;
-static DEFINE_SPINLOCK(timer_lock);
-static struct timer_list timerlist;
-/* time of last signal change detected */
-static struct timeval last_tv = {0, 0};
-/* time of last UART data ready interrupt */
-static struct timeval last_intr_tv = {0, 0};
-static int last_value;
-
-static DECLARE_WAIT_QUEUE_HEAD(lirc_read_queue);
-
-static DEFINE_SPINLOCK(hardware_lock);
-static DEFINE_SPINLOCK(dev_lock);
-static bool device_open;
-
-static int rx_buf[RBUF_LEN];
-unsigned int rx_tail, rx_head;
-
-static struct pnp_driver it87_pnp_driver;
-
-/* SECTION: Prototypes */
-
-/* Communication with user-space */
-static int lirc_open(struct inode *inode, struct file *file);
-static int lirc_close(struct inode *inode, struct file *file);
-static unsigned int lirc_poll(struct file *file, poll_table *wait);
-static ssize_t lirc_read(struct file *file, char *buf,
- size_t count, loff_t *ppos);
-static ssize_t lirc_write(struct file *file, const char *buf,
- size_t n, loff_t *pos);
-static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
-static void add_read_queue(int flag, unsigned long val);
-static int init_chrdev(void);
-static void drop_chrdev(void);
-/* Hardware */
-static irqreturn_t it87_interrupt(int irq, void *dev_id);
-static void send_space(unsigned long len);
-static void send_pulse(unsigned long len);
-static void init_send(void);
-static void terminate_send(unsigned long len);
-static int init_hardware(void);
-static void drop_hardware(void);
-/* Initialisation */
-static int init_port(void);
-static void drop_port(void);
-
-
-/* SECTION: Communication with user-space */
-
-static int lirc_open(struct inode *inode, struct file *file)
-{
- spin_lock(&dev_lock);
- if (device_open) {
- spin_unlock(&dev_lock);
- return -EBUSY;
- }
- device_open = true;
- spin_unlock(&dev_lock);
- return 0;
-}
-
-
-static int lirc_close(struct inode *inode, struct file *file)
-{
- spin_lock(&dev_lock);
- device_open = false;
- spin_unlock(&dev_lock);
- return 0;
-}
-
-
-static unsigned int lirc_poll(struct file *file, poll_table *wait)
-{
- poll_wait(file, &lirc_read_queue, wait);
- if (rx_head != rx_tail)
- return POLLIN | POLLRDNORM;
- return 0;
-}
-
-
-static ssize_t lirc_read(struct file *file, char *buf,
- size_t count, loff_t *ppos)
-{
- int n = 0;
- int retval = 0;
-
- while (n < count) {
- if (file->f_flags & O_NONBLOCK && rx_head == rx_tail) {
- retval = -EAGAIN;
- break;
- }
- retval = wait_event_interruptible(lirc_read_queue,
- rx_head != rx_tail);
- if (retval)
- break;
-
- if (copy_to_user((void *) buf + n, (void *) (rx_buf + rx_head),
- sizeof(int))) {
- retval = -EFAULT;
- break;
- }
- rx_head = (rx_head + 1) & (RBUF_LEN - 1);
- n += sizeof(int);
- }
- if (n)
- return n;
- return retval;
-}
-
-
-static ssize_t lirc_write(struct file *file, const char *buf,
- size_t n, loff_t *pos)
-{
- int i = 0;
- int *tx_buf;
-
- if (n % sizeof(int))
- return -EINVAL;
- tx_buf = memdup_user(buf, n);
- if (IS_ERR(tx_buf))
- return PTR_ERR(tx_buf);
- n /= sizeof(int);
- init_send();
- while (1) {
- if (i >= n)
- break;
- if (tx_buf[i])
- send_pulse(tx_buf[i]);
- i++;
- if (i >= n)
- break;
- if (tx_buf[i])
- send_space(tx_buf[i]);
- i++;
- }
- terminate_send(tx_buf[i - 1]);
- kfree(tx_buf);
- return n;
-}
-
-
-static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
-{
- int retval = 0;
- __u32 value = 0;
- unsigned long hw_flags;
-
- if (cmd == LIRC_GET_FEATURES)
- value = LIRC_CAN_SEND_PULSE |
- LIRC_CAN_SET_SEND_CARRIER |
- LIRC_CAN_REC_MODE2;
- else if (cmd == LIRC_GET_SEND_MODE)
- value = LIRC_MODE_PULSE;
- else if (cmd == LIRC_GET_REC_MODE)
- value = LIRC_MODE_MODE2;
-
- switch (cmd) {
- case LIRC_GET_FEATURES:
- case LIRC_GET_SEND_MODE:
- case LIRC_GET_REC_MODE:
- retval = put_user(value, (__u32 *) arg);
- break;
-
- case LIRC_SET_SEND_MODE:
- case LIRC_SET_REC_MODE:
- retval = get_user(value, (__u32 *) arg);
- break;
-
- case LIRC_SET_SEND_CARRIER:
- retval = get_user(value, (__u32 *) arg);
- if (retval)
- return retval;
- value /= 1000;
- if (value > IT87_CIR_FREQ_MAX ||
- value < IT87_CIR_FREQ_MIN)
- return -EINVAL;
-
- it87_freq = value;
-
- spin_lock_irqsave(&hardware_lock, hw_flags);
- outb(((inb(io + IT87_CIR_TCR2) & IT87_CIR_TCR2_TXMPW) |
- (it87_freq - IT87_CIR_FREQ_MIN) << 3),
- io + IT87_CIR_TCR2);
- spin_unlock_irqrestore(&hardware_lock, hw_flags);
- dprintk("demodulation frequency: %d kHz\n", it87_freq);
-
- break;
-
- default:
- retval = -EINVAL;
- }
-
- if (retval)
- return retval;
-
- if (cmd == LIRC_SET_REC_MODE) {
- if (value != LIRC_MODE_MODE2)
- retval = -ENOSYS;
- } else if (cmd == LIRC_SET_SEND_MODE) {
- if (value != LIRC_MODE_PULSE)
- retval = -ENOSYS;
- }
- return retval;
-}
-
-static void add_read_queue(int flag, unsigned long val)
-{
- unsigned int new_rx_tail;
- int newval;
-
- dprintk("add flag %d with val %lu\n", flag, val);
-
- newval = val & PULSE_MASK;
-
- /*
- * statistically, pulses are ~TIME_CONST/2 too long. we could
- * maybe make this more exact, but this is good enough
- */
- if (flag) {
- /* pulse */
- if (newval > TIME_CONST / 2)
- newval -= TIME_CONST / 2;
- else /* should not ever happen */
- newval = 1;
- newval |= PULSE_BIT;
- } else
- newval += TIME_CONST / 2;
- new_rx_tail = (rx_tail + 1) & (RBUF_LEN - 1);
- if (new_rx_tail == rx_head) {
- dprintk("Buffer overrun.\n");
- return;
- }
- rx_buf[rx_tail] = newval;
- rx_tail = new_rx_tail;
- wake_up_interruptible(&lirc_read_queue);
-}
-
-
-static const struct file_operations lirc_fops = {
- .owner = THIS_MODULE,
- .read = lirc_read,
- .write = lirc_write,
- .poll = lirc_poll,
- .unlocked_ioctl = lirc_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = lirc_ioctl,
-#endif
- .open = lirc_open,
- .release = lirc_close,
- .llseek = noop_llseek,
-};
-
-static int set_use_inc(void *data)
-{
- return 0;
-}
-
-static void set_use_dec(void *data)
-{
-}
-
-static struct lirc_driver driver = {
- .name = LIRC_DRIVER_NAME,
- .minor = -1,
- .code_length = 1,
- .sample_rate = 0,
- .data = NULL,
- .add_to_buf = NULL,
- .set_use_inc = set_use_inc,
- .set_use_dec = set_use_dec,
- .fops = &lirc_fops,
- .dev = NULL,
- .owner = THIS_MODULE,
-};
-
-
-static int init_chrdev(void)
-{
- driver.minor = lirc_register_driver(&driver);
-
- if (driver.minor < 0) {
- printk(KERN_ERR LIRC_DRIVER_NAME ": init_chrdev() failed.\n");
- return -EIO;
- }
- return 0;
-}
-
-
-static void drop_chrdev(void)
-{
- lirc_unregister_driver(driver.minor);
-}
-
-
-/* SECTION: Hardware */
-static long delta(struct timeval *tv1, struct timeval *tv2)
-{
- unsigned long deltv;
-
- deltv = tv2->tv_sec - tv1->tv_sec;
- if (deltv > 15)
- deltv = 0xFFFFFF;
- else
- deltv = deltv*1000000 + tv2->tv_usec - tv1->tv_usec;
- return deltv;
-}
-
-static void it87_timeout(unsigned long data)
-{
- unsigned long flags;
-
- /* avoid interference with interrupt */
- spin_lock_irqsave(&timer_lock, flags);
-
- if (digimatrix) {
- /* We have timed out. Disable the RX mechanism. */
-
- outb((inb(io + IT87_CIR_RCR) & ~IT87_CIR_RCR_RXEN) |
- IT87_CIR_RCR_RXACT, io + IT87_CIR_RCR);
- if (it87_RXEN_mask)
- outb(inb(io + IT87_CIR_RCR) | IT87_CIR_RCR_RXEN,
- io + IT87_CIR_RCR);
- dprintk(" TIMEOUT\n");
- timer_enabled = 0;
-
- /* fifo clear */
- outb(inb(io + IT87_CIR_TCR1) | IT87_CIR_TCR1_FIFOCLR,
- io+IT87_CIR_TCR1);
-
- } else {
- /*
- * if last received signal was a pulse, but receiving stopped
- * within the 9 bit frame, we need to finish this pulse and
- * simulate a signal change to from pulse to space. Otherwise
- * upper layers will receive two sequences next time.
- */
-
- if (last_value) {
- unsigned long pulse_end;
-
- /* determine 'virtual' pulse end: */
- pulse_end = delta(&last_tv, &last_intr_tv);
- dprintk("timeout add %d for %lu usec\n",
- last_value, pulse_end);
- add_read_queue(last_value, pulse_end);
- last_value = 0;
- last_tv = last_intr_tv;
- }
- }
- spin_unlock_irqrestore(&timer_lock, flags);
-}
-
-static irqreturn_t it87_interrupt(int irq, void *dev_id)
-{
- unsigned char data;
- struct timeval curr_tv;
- static unsigned long deltv;
- unsigned long deltintrtv;
- unsigned long flags, hw_flags;
- int iir, lsr;
- int fifo = 0;
- static char lastbit;
- char bit;
-
- /* Bit duration in microseconds */
- const unsigned long bit_duration = 1000000ul /
- (115200 / IT87_CIR_BAUDRATE_DIVISOR);
-
-
- iir = inb(io + IT87_CIR_IIR);
-
- switch (iir & IT87_CIR_IIR_IID) {
- case 0x4:
- case 0x6:
- lsr = inb(io + IT87_CIR_RSR) & (IT87_CIR_RSR_RXFTO |
- IT87_CIR_RSR_RXFBC);
- fifo = lsr & IT87_CIR_RSR_RXFBC;
- dprintk("iir: 0x%x fifo: 0x%x\n", iir, lsr);
-
- /* avoid interference with timer */
- spin_lock_irqsave(&timer_lock, flags);
- spin_lock_irqsave(&hardware_lock, hw_flags);
- if (digimatrix) {
- static unsigned long acc_pulse;
- static unsigned long acc_space;
-
- do {
- data = inb(io + IT87_CIR_DR);
- data = ~data;
- fifo--;
- if (data != 0x00) {
- if (timer_enabled)
- del_timer(&timerlist);
- /*
- * start timer for end of
- * sequence detection
- */
- timerlist.expires = jiffies +
- IT87_TIMEOUT;
- add_timer(&timerlist);
- timer_enabled = 1;
- }
- /* Loop through */
- for (bit = 0; bit < 8; ++bit) {
- if ((data >> bit) & 1) {
- ++acc_pulse;
- if (lastbit == 0) {
- add_read_queue(0,
- acc_space *
- bit_duration);
- acc_space = 0;
- }
- } else {
- ++acc_space;
- if (lastbit == 1) {
- add_read_queue(1,
- acc_pulse *
- bit_duration);
- acc_pulse = 0;
- }
- }
- lastbit = (data >> bit) & 1;
- }
-
- } while (fifo != 0);
- } else { /* Normal Operation */
- do {
- del_timer(&timerlist);
- data = inb(io + IT87_CIR_DR);
-
- dprintk("data=%02x\n", data);
- do_gettimeofday(&curr_tv);
- deltv = delta(&last_tv, &curr_tv);
- deltintrtv = delta(&last_intr_tv, &curr_tv);
-
- dprintk("t %lu , d %d\n",
- deltintrtv, (int)data);
-
- /*
- * if nothing came in last 2 cycles,
- * it was gap
- */
- if (deltintrtv > TIME_CONST * 2) {
- if (last_value) {
- dprintk("GAP\n");
-
- /* simulate signal change */
- add_read_queue(last_value,
- deltv -
- deltintrtv);
- last_value = 0;
- last_tv.tv_sec =
- last_intr_tv.tv_sec;
- last_tv.tv_usec =
- last_intr_tv.tv_usec;
- deltv = deltintrtv;
- }
- }
- data = 1;
- if (data ^ last_value) {
- /*
- * deltintrtv > 2*TIME_CONST,
- * remember ? the other case is
- * timeout
- */
- add_read_queue(last_value,
- deltv-TIME_CONST);
- last_value = data;
- last_tv = curr_tv;
- if (last_tv.tv_usec >= TIME_CONST)
- last_tv.tv_usec -= TIME_CONST;
- else {
- last_tv.tv_sec--;
- last_tv.tv_usec += 1000000 -
- TIME_CONST;
- }
- }
- last_intr_tv = curr_tv;
- if (data) {
- /*
- * start timer for end of
- * sequence detection
- */
- timerlist.expires =
- jiffies + IT87_TIMEOUT;
- add_timer(&timerlist);
- }
- outb((inb(io + IT87_CIR_RCR) &
- ~IT87_CIR_RCR_RXEN) |
- IT87_CIR_RCR_RXACT,
- io + IT87_CIR_RCR);
- if (it87_RXEN_mask)
- outb(inb(io + IT87_CIR_RCR) |
- IT87_CIR_RCR_RXEN,
- io + IT87_CIR_RCR);
- fifo--;
- } while (fifo != 0);
- }
- spin_unlock_irqrestore(&hardware_lock, hw_flags);
- spin_unlock_irqrestore(&timer_lock, flags);
-
- return IRQ_RETVAL(IRQ_HANDLED);
-
- default:
- /* not our irq */
- dprintk("unknown IRQ (shouldn't happen) !!\n");
- return IRQ_RETVAL(IRQ_NONE);
- }
-}
-
-
-static void send_it87(unsigned long len, unsigned long stime,
- unsigned char send_byte, unsigned int count_bits)
-{
- long count = len / stime;
- long time_left = 0;
- static unsigned char byte_out;
- unsigned long hw_flags;
-
- dprintk("%s: len=%ld, sb=%d\n", __func__, len, send_byte);
-
- time_left = (long)len - (long)count * (long)stime;
- count += ((2 * time_left) / stime);
- while (count) {
- long i = 0;
- for (i = 0; i < count_bits; i++) {
- byte_out = (byte_out << 1) | (send_byte & 1);
- it87_bits_in_byte_out++;
- }
- if (it87_bits_in_byte_out == 8) {
- dprintk("out=0x%x, tsr_txfbc: 0x%x\n",
- byte_out,
- inb(io + IT87_CIR_TSR) &
- IT87_CIR_TSR_TXFBC);
-
- while ((inb(io + IT87_CIR_TSR) &
- IT87_CIR_TSR_TXFBC) >= IT87_CIR_FIFO_SIZE)
- ;
-
- spin_lock_irqsave(&hardware_lock, hw_flags);
- outb(byte_out, io + IT87_CIR_DR);
- spin_unlock_irqrestore(&hardware_lock, hw_flags);
-
- it87_bits_in_byte_out = 0;
- it87_send_counter++;
- byte_out = 0;
- }
- count--;
- }
-}
-
-
-/*TODO: maybe exchange space and pulse because it8705 only modulates 0-bits */
-
-static void send_space(unsigned long len)
-{
- send_it87(len, TIME_CONST, IT87_CIR_SPACE, IT87_CIR_BAUDRATE_DIVISOR);
-}
-
-static void send_pulse(unsigned long len)
-{
- send_it87(len, TIME_CONST, IT87_CIR_PULSE, IT87_CIR_BAUDRATE_DIVISOR);
-}
-
-
-static void init_send()
-{
- unsigned long flags;
-
- spin_lock_irqsave(&hardware_lock, flags);
- /* RXEN=0: receiver disable */
- it87_RXEN_mask = 0;
- outb(inb(io + IT87_CIR_RCR) & ~IT87_CIR_RCR_RXEN,
- io + IT87_CIR_RCR);
- spin_unlock_irqrestore(&hardware_lock, flags);
- it87_bits_in_byte_out = 0;
- it87_send_counter = 0;
-}
-
-
-static void terminate_send(unsigned long len)
-{
- unsigned long flags;
- unsigned long last = 0;
-
- last = it87_send_counter;
- /* make sure all necessary data has been sent */
- while (last == it87_send_counter)
- send_space(len);
- /* wait until all data sent */
- while ((inb(io + IT87_CIR_TSR) & IT87_CIR_TSR_TXFBC) != 0)
- ;
- /* then re-enable receiver */
- spin_lock_irqsave(&hardware_lock, flags);
- it87_RXEN_mask = IT87_CIR_RCR_RXEN;
- outb(inb(io + IT87_CIR_RCR) | IT87_CIR_RCR_RXEN,
- io + IT87_CIR_RCR);
- spin_unlock_irqrestore(&hardware_lock, flags);
-}
-
-
-static int init_hardware(void)
-{
- unsigned long flags;
- unsigned char it87_rcr = 0;
-
- spin_lock_irqsave(&hardware_lock, flags);
- /* init cir-port */
- /* enable r/w-access to Baudrate-Register */
- outb(IT87_CIR_IER_BR, io + IT87_CIR_IER);
- outb(IT87_CIR_BAUDRATE_DIVISOR % 0x100, io+IT87_CIR_BDLR);
- outb(IT87_CIR_BAUDRATE_DIVISOR / 0x100, io+IT87_CIR_BDHR);
- /* Baudrate Register off, define IRQs: Input only */
- if (digimatrix) {
- outb(IT87_CIR_IER_IEC | IT87_CIR_IER_RFOIE, io + IT87_CIR_IER);
- /* RX: HCFS=0, RXDCR = 001b (33,75..38,25 kHz), RXEN=1 */
- } else {
- outb(IT87_CIR_IER_IEC | IT87_CIR_IER_RDAIE, io + IT87_CIR_IER);
- /* RX: HCFS=0, RXDCR = 001b (35,6..40,3 kHz), RXEN=1 */
- }
- it87_rcr = (IT87_CIR_RCR_RXEN & it87_RXEN_mask) | 0x1;
- if (it87_enable_demodulator)
- it87_rcr |= IT87_CIR_RCR_RXEND;
- outb(it87_rcr, io + IT87_CIR_RCR);
- if (digimatrix) {
- /* Set FIFO depth to 1 byte, and disable TX */
- outb(inb(io + IT87_CIR_TCR1) | 0x00,
- io + IT87_CIR_TCR1);
-
- /*
- * TX: it87_freq (36kHz), 'reserved' sensitivity
- * setting (0x00)
- */
- outb(((it87_freq - IT87_CIR_FREQ_MIN) << 3) | 0x00,
- io + IT87_CIR_TCR2);
- } else {
- /* TX: 38kHz, 13,3us (pulse-width) */
- outb(((it87_freq - IT87_CIR_FREQ_MIN) << 3) | 0x06,
- io + IT87_CIR_TCR2);
- }
- spin_unlock_irqrestore(&hardware_lock, flags);
- return 0;
-}
-
-
-static void drop_hardware(void)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&hardware_lock, flags);
- disable_irq(irq);
- /* receiver disable */
- it87_RXEN_mask = 0;
- outb(0x1, io + IT87_CIR_RCR);
- /* turn off irqs */
- outb(0, io + IT87_CIR_IER);
- /* fifo clear */
- outb(IT87_CIR_TCR1_FIFOCLR, io+IT87_CIR_TCR1);
- /* reset */
- outb(IT87_CIR_IER_RESET, io+IT87_CIR_IER);
- enable_irq(irq);
- spin_unlock_irqrestore(&hardware_lock, flags);
-}
-
-
-static unsigned char it87_read(unsigned char port)
-{
- outb(port, IT87_ADRPORT);
- return inb(IT87_DATAPORT);
-}
-
-
-static void it87_write(unsigned char port, unsigned char data)
-{
- outb(port, IT87_ADRPORT);
- outb(data, IT87_DATAPORT);
-}
-
-
-/* SECTION: Initialisation */
-
-static int init_port(void)
-{
- unsigned long hw_flags;
- int retval = 0;
-
- unsigned char init_bytes[4] = IT87_INIT;
- unsigned char it87_chipid = 0;
- unsigned char ldn = 0;
- unsigned int it87_io = 0;
- unsigned int it87_irq = 0;
-
- /* Enter MB PnP Mode */
- outb(init_bytes[0], IT87_ADRPORT);
- outb(init_bytes[1], IT87_ADRPORT);
- outb(init_bytes[2], IT87_ADRPORT);
- outb(init_bytes[3], IT87_ADRPORT);
-
- /* 8712 or 8705 ? */
- it87_chipid = it87_read(IT87_CHIP_ID1);
- if (it87_chipid != 0x87) {
- retval = -ENXIO;
- return retval;
- }
- it87_chipid = it87_read(IT87_CHIP_ID2);
- if ((it87_chipid != 0x05) &&
- (it87_chipid != 0x12) &&
- (it87_chipid != 0x18) &&
- (it87_chipid != 0x20)) {
- printk(KERN_INFO LIRC_DRIVER_NAME
- ": no IT8704/05/12/18/20 found (claimed IT87%02x), "
- "exiting..\n", it87_chipid);
- retval = -ENXIO;
- return retval;
- }
- printk(KERN_INFO LIRC_DRIVER_NAME
- ": found IT87%02x.\n",
- it87_chipid);
-
- /* get I/O-Port and IRQ */
- if (it87_chipid == 0x12 || it87_chipid == 0x18)
- ldn = IT8712_CIR_LDN;
- else
- ldn = IT8705_CIR_LDN;
- it87_write(IT87_LDN, ldn);
-
- it87_io = it87_read(IT87_CIR_BASE_MSB) * 256 +
- it87_read(IT87_CIR_BASE_LSB);
- if (it87_io == 0) {
- if (io == 0)
- io = IT87_CIR_DEFAULT_IOBASE;
- printk(KERN_INFO LIRC_DRIVER_NAME
- ": set default io 0x%x\n",
- io);
- it87_write(IT87_CIR_BASE_MSB, io / 0x100);
- it87_write(IT87_CIR_BASE_LSB, io % 0x100);
- } else
- io = it87_io;
-
- it87_irq = it87_read(IT87_CIR_IRQ);
- if (digimatrix || it87_irq == 0) {
- if (irq == 0)
- irq = IT87_CIR_DEFAULT_IRQ;
- printk(KERN_INFO LIRC_DRIVER_NAME
- ": set default irq 0x%x\n",
- irq);
- it87_write(IT87_CIR_IRQ, irq);
- } else
- irq = it87_irq;
-
- spin_lock_irqsave(&hardware_lock, hw_flags);
- /* reset */
- outb(IT87_CIR_IER_RESET, io+IT87_CIR_IER);
- /* fifo clear */
- outb(IT87_CIR_TCR1_FIFOCLR |
- /* IT87_CIR_TCR1_ILE | */
- IT87_CIR_TCR1_TXRLE |
- IT87_CIR_TCR1_TXENDF, io+IT87_CIR_TCR1);
- spin_unlock_irqrestore(&hardware_lock, hw_flags);
-
- /* get I/O port access and IRQ line */
- if (request_region(io, 8, LIRC_DRIVER_NAME) == NULL) {
- printk(KERN_ERR LIRC_DRIVER_NAME
- ": i/o port 0x%.4x already in use.\n", io);
- /* Leaving MB PnP Mode */
- it87_write(IT87_CFGCTRL, 0x2);
- return -EBUSY;
- }
-
- /* activate CIR-Device */
- it87_write(IT87_CIR_ACT, 0x1);
-
- /* Leaving MB PnP Mode */
- it87_write(IT87_CFGCTRL, 0x2);
-
- retval = request_irq(irq, it87_interrupt, 0 /*IRQF_DISABLED*/,
- LIRC_DRIVER_NAME, NULL);
- if (retval < 0) {
- printk(KERN_ERR LIRC_DRIVER_NAME
- ": IRQ %d already in use.\n",
- irq);
- release_region(io, 8);
- return retval;
- }
-
- printk(KERN_INFO LIRC_DRIVER_NAME
- ": I/O port 0x%.4x, IRQ %d.\n", io, irq);
-
- init_timer(&timerlist);
- timerlist.function = it87_timeout;
- timerlist.data = 0xabadcafe;
-
- return 0;
-}
-
-
-static void drop_port(void)
-{
-#if 0
- unsigned char init_bytes[4] = IT87_INIT;
-
- /* Enter MB PnP Mode */
- outb(init_bytes[0], IT87_ADRPORT);
- outb(init_bytes[1], IT87_ADRPORT);
- outb(init_bytes[2], IT87_ADRPORT);
- outb(init_bytes[3], IT87_ADRPORT);
-
- /* deactivate CIR-Device */
- it87_write(IT87_CIR_ACT, 0x0);
-
- /* Leaving MB PnP Mode */
- it87_write(IT87_CFGCTRL, 0x2);
-#endif
-
- del_timer_sync(&timerlist);
- free_irq(irq, NULL);
- release_region(io, 8);
-}
-
-
-static int init_lirc_it87(void)
-{
- int retval;
-
- init_waitqueue_head(&lirc_read_queue);
- retval = init_port();
- if (retval < 0)
- return retval;
- init_hardware();
- printk(KERN_INFO LIRC_DRIVER_NAME ": Installed.\n");
- return 0;
-}
-
-static int it87_probe(struct pnp_dev *pnp_dev,
- const struct pnp_device_id *dev_id)
-{
- int retval;
-
- driver.dev = &pnp_dev->dev;
-
- retval = init_chrdev();
- if (retval < 0)
- return retval;
-
- retval = init_lirc_it87();
- if (retval)
- goto init_lirc_it87_failed;
-
- return 0;
-
-init_lirc_it87_failed:
- drop_chrdev();
-
- return retval;
-}
-
-static int __init lirc_it87_init(void)
-{
- return pnp_register_driver(&it87_pnp_driver);
-}
-
-
-static void __exit lirc_it87_exit(void)
-{
- drop_hardware();
- drop_chrdev();
- drop_port();
- pnp_unregister_driver(&it87_pnp_driver);
- printk(KERN_INFO LIRC_DRIVER_NAME ": Uninstalled.\n");
-}
-
-/* SECTION: PNP for ITE8704/13/18 */
-
-static const struct pnp_device_id pnp_dev_table[] = {
- {"ITE8704", 0},
- {"ITE8713", 0},
- {}
-};
-
-MODULE_DEVICE_TABLE(pnp, pnp_dev_table);
-
-static struct pnp_driver it87_pnp_driver = {
- .name = LIRC_DRIVER_NAME,
- .id_table = pnp_dev_table,
- .probe = it87_probe,
-};
-
-module_init(lirc_it87_init);
-module_exit(lirc_it87_exit);
-
-MODULE_DESCRIPTION("LIRC driver for ITE IT8704/05/12/18/20 CIR port");
-MODULE_AUTHOR("Hans-Gunter Lutke Uphues");
-MODULE_LICENSE("GPL");
-
-module_param(io, int, S_IRUGO);
-MODULE_PARM_DESC(io, "I/O base address (default: 0x310)");
-
-module_param(irq, int, S_IRUGO);
-#ifdef LIRC_IT87_DIGIMATRIX
-MODULE_PARM_DESC(irq, "Interrupt (1,3-12) (default: 9)");
-#else
-MODULE_PARM_DESC(irq, "Interrupt (1,3-12) (default: 7)");
-#endif
-
-module_param(it87_enable_demodulator, bool, S_IRUGO);
-MODULE_PARM_DESC(it87_enable_demodulator,
- "Receiver demodulator enable/disable (1/0), default: 0");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Enable debugging messages");
-
-module_param(digimatrix, bool, S_IRUGO | S_IWUSR);
-#ifdef LIRC_IT87_DIGIMATRIX
-MODULE_PARM_DESC(digimatrix,
- "Asus Digimatrix it87 compat. enable/disable (1/0), default: 1");
-#else
-MODULE_PARM_DESC(digimatrix,
- "Asus Digimatrix it87 compat. enable/disable (1/0), default: 0");
-#endif
-
-
-module_param(it87_freq, int, S_IRUGO);
-#ifdef LIRC_IT87_DIGIMATRIX
-MODULE_PARM_DESC(it87_freq,
- "Carrier demodulator frequency (kHz), (default: 36)");
-#else
-MODULE_PARM_DESC(it87_freq,
- "Carrier demodulator frequency (kHz), (default: 38)");
-#endif
diff --git a/drivers/staging/lirc/lirc_it87.h b/drivers/staging/lirc/lirc_it87.h
deleted file mode 100644
index cf021c8..0000000
--- a/drivers/staging/lirc/lirc_it87.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/* lirc_it87.h */
-/* SECTION: Definitions */
-
-/********************************* ITE IT87xx ************************/
-
-/* based on the following documentation from ITE:
- a) IT8712F Preliminary CIR Programming Guide V0.1
- b) IT8705F Simple LPC I/O Preliminary Specification V0.3
- c) IT8712F EC-LPC I/O Preliminary Specification V0.5
-*/
-
-/* IT8712/05 Ports: */
-#define IT87_ADRPORT 0x2e
-#define IT87_DATAPORT 0x2f
-#define IT87_INIT {0x87, 0x01, 0x55, 0x55}
-
-/* alternate Ports: */
-/*
-#define IT87_ADRPORT 0x4e
-#define IT87_DATAPORT 0x4f
-#define IT87_INIT {0x87, 0x01, 0x55, 0xaa}
- */
-
-/* IT8712/05 Registers */
-#define IT87_CFGCTRL 0x2
-#define IT87_LDN 0x7
-#define IT87_CHIP_ID1 0x20
-#define IT87_CHIP_ID2 0x21
-#define IT87_CFG_VERSION 0x22
-#define IT87_SWSUSPEND 0x23
-
-#define IT8712_CIR_LDN 0xa
-#define IT8705_CIR_LDN 0x7
-
-/* CIR Configuration Registers: */
-#define IT87_CIR_ACT 0x30
-#define IT87_CIR_BASE_MSB 0x60
-#define IT87_CIR_BASE_LSB 0x61
-#define IT87_CIR_IRQ 0x70
-#define IT87_CIR_CONFIG 0xf0
-
-/* List of IT87_CIR registers: offset to BaseAddr */
-#define IT87_CIR_DR 0
-#define IT87_CIR_IER 1
-#define IT87_CIR_RCR 2
-#define IT87_CIR_TCR1 3
-#define IT87_CIR_TCR2 4
-#define IT87_CIR_TSR 5
-#define IT87_CIR_RSR 6
-#define IT87_CIR_BDLR 5
-#define IT87_CIR_BDHR 6
-#define IT87_CIR_IIR 7
-
-/* Bit Definition */
-/* IER: */
-#define IT87_CIR_IER_TM_EN 0x80
-#define IT87_CIR_IER_RESEVED 0x40
-#define IT87_CIR_IER_RESET 0x20
-#define IT87_CIR_IER_BR 0x10
-#define IT87_CIR_IER_IEC 0x8
-#define IT87_CIR_IER_RFOIE 0x4
-#define IT87_CIR_IER_RDAIE 0x2
-#define IT87_CIR_IER_TLDLIE 0x1
-
-/* RCR: */
-#define IT87_CIR_RCR_RDWOS 0x80
-#define IT87_CIR_RCR_HCFS 0x40
-#define IT87_CIR_RCR_RXEN 0x20
-#define IT87_CIR_RCR_RXEND 0x10
-#define IT87_CIR_RCR_RXACT 0x8
-#define IT87_CIR_RCR_RXDCR 0x7
-
-/* TCR1: */
-#define IT87_CIR_TCR1_FIFOCLR 0x80
-#define IT87_CIR_TCR1_ILE 0x40
-#define IT87_CIR_TCR1_FIFOTL 0x30
-#define IT87_CIR_TCR1_TXRLE 0x8
-#define IT87_CIR_TCR1_TXENDF 0x4
-#define IT87_CIR_TCR1_TXMPM 0x3
-
-/* TCR2: */
-#define IT87_CIR_TCR2_CFQ 0xf8
-#define IT87_CIR_TCR2_TXMPW 0x7
-
-/* TSR: */
-#define IT87_CIR_TSR_RESERVED 0xc0
-#define IT87_CIR_TSR_TXFBC 0x3f
-
-/* RSR: */
-#define IT87_CIR_RSR_RXFTO 0x80
-#define IT87_CIR_RSR_RESERVED 0x40
-#define IT87_CIR_RSR_RXFBC 0x3f
-
-/* IIR: */
-#define IT87_CIR_IIR_RESERVED 0xf8
-#define IT87_CIR_IIR_IID 0x6
-#define IT87_CIR_IIR_IIP 0x1
-
-/* TM: */
-#define IT87_CIR_TM_IL_SEL 0x80
-#define IT87_CIR_TM_RESERVED 0x40
-#define IT87_CIR_TM_TM_REG 0x3f
-
-#define IT87_CIR_FIFO_SIZE 32
-
-/* Baudratedivisor for IT87: power of 2: only 1,2,4 or 8) */
-#define IT87_CIR_BAUDRATE_DIVISOR 0x1
-#define IT87_CIR_DEFAULT_IOBASE 0x310
-#define IT87_CIR_DEFAULT_IRQ 0x7
-#define IT87_CIR_SPACE 0x00
-#define IT87_CIR_PULSE 0xff
-#define IT87_CIR_FREQ_MIN 27
-#define IT87_CIR_FREQ_MAX 58
-#define TIME_CONST (IT87_CIR_BAUDRATE_DIVISOR * 8000000ul / 115200ul)
-
-/********************************* ITE IT87xx ************************/
diff --git a/drivers/staging/lirc/lirc_ite8709.c b/drivers/staging/lirc/lirc_ite8709.c
deleted file mode 100644
index cb20cfd..0000000
--- a/drivers/staging/lirc/lirc_ite8709.c
+++ /dev/null
@@ -1,542 +0,0 @@
-/*
- * LIRC driver for ITE8709 CIR port
- *
- * Copyright (C) 2008 Grégory Lardière <spmf2004-lirc@yahoo.fr>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
- */
-
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/pnp.h>
-#include <linux/io.h>
-
-#include <media/lirc.h>
-#include <media/lirc_dev.h>
-
-#define LIRC_DRIVER_NAME "lirc_ite8709"
-
-#define BUF_CHUNK_SIZE sizeof(int)
-#define BUF_SIZE (128*BUF_CHUNK_SIZE)
-
-/*
- * The ITE8709 device seems to be the combination of IT8512 superIO chip and
- * a specific firmware running on the IT8512's embedded micro-controller.
- * In addition of the embedded micro-controller, the IT8512 chip contains a
- * CIR module and several other modules. A few modules are directly accessible
- * by the host CPU, but most of them are only accessible by the
- * micro-controller. The CIR module is only accessible by the micro-controller.
- * The battery-backed SRAM module is accessible by the host CPU and the
- * micro-controller. So one of the MC's firmware role is to act as a bridge
- * between the host CPU and the CIR module. The firmware implements a kind of
- * communication protocol using the SRAM module as a shared memory. The IT8512
- * specification is publicly available on ITE's web site, but the communication
- * protocol is not, so it was reverse-engineered.
- */
-
-/* ITE8709 Registers addresses and values (reverse-engineered) */
-#define ITE8709_MODE 0x1a
-#define ITE8709_REG_ADR 0x1b
-#define ITE8709_REG_VAL 0x1c
-#define ITE8709_IIR 0x1e /* Interrupt identification register */
-#define ITE8709_RFSR 0x1f /* Receiver FIFO status register */
-#define ITE8709_FIFO_START 0x20
-
-#define ITE8709_MODE_READY 0X00
-#define ITE8709_MODE_WRITE 0X01
-#define ITE8709_MODE_READ 0X02
-#define ITE8709_IIR_RDAI 0x02 /* Receiver data available interrupt */
-#define ITE8709_IIR_RFOI 0x04 /* Receiver FIFO overrun interrupt */
-#define ITE8709_RFSR_MASK 0x3f /* FIFO byte count mask */
-
-/*
- * IT8512 CIR-module registers addresses and values
- * (from IT8512 E/F specification v0.4.1)
- */
-#define IT8512_REG_MSTCR 0x01 /* Master control register */
-#define IT8512_REG_IER 0x02 /* Interrupt enable register */
-#define IT8512_REG_CFR 0x04 /* Carrier frequency register */
-#define IT8512_REG_RCR 0x05 /* Receive control register */
-#define IT8512_REG_BDLR 0x08 /* Baud rate divisor low byte register */
-#define IT8512_REG_BDHR 0x09 /* Baud rate divisor high byte register */
-
-#define IT8512_MSTCR_RESET 0x01 /* Reset registers to default value */
-#define IT8512_MSTCR_FIFOCLR 0x02 /* Clear FIFO */
-#define IT8512_MSTCR_FIFOTL_7 0x04 /* FIFO threshold level : 7 */
-#define IT8512_MSTCR_FIFOTL_25 0x0c /* FIFO threshold level : 25 */
-#define IT8512_IER_RDAIE 0x02 /* Enable data interrupt request */
-#define IT8512_IER_RFOIE 0x04 /* Enable FIFO overrun interrupt req */
-#define IT8512_IER_IEC 0x80 /* Enable interrupt request */
-#define IT8512_CFR_CF_36KHZ 0x09 /* Carrier freq : low speed, 36kHz */
-#define IT8512_RCR_RXDCR_1 0x01 /* Demodulation carrier range : 1 */
-#define IT8512_RCR_RXACT 0x08 /* Receiver active */
-#define IT8512_RCR_RXEN 0x80 /* Receiver enable */
-#define IT8512_BDR_6 6 /* Baud rate divisor : 6 */
-
-/* Actual values used by this driver */
-#define CFG_FIFOTL IT8512_MSTCR_FIFOTL_25
-#define CFG_CR_FREQ IT8512_CFR_CF_36KHZ
-#define CFG_DCR IT8512_RCR_RXDCR_1
-#define CFG_BDR IT8512_BDR_6
-#define CFG_TIMEOUT 100000 /* Rearm interrupt when a space is > 100 ms */
-
-static int debug;
-
-struct ite8709_device {
- int use_count;
- int io;
- int irq;
- spinlock_t hardware_lock;
- __u64 acc_pulse;
- __u64 acc_space;
- char lastbit;
- struct timeval last_tv;
- struct lirc_driver driver;
- struct tasklet_struct tasklet;
- char force_rearm;
- char rearmed;
- char device_busy;
-};
-
-#define dprintk(fmt, args...) \
- do { \
- if (debug) \
- printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \
- fmt, ## args); \
- } while (0)
-
-
-static unsigned char ite8709_read(struct ite8709_device *dev,
- unsigned char port)
-{
- outb(port, dev->io);
- return inb(dev->io+1);
-}
-
-static void ite8709_write(struct ite8709_device *dev, unsigned char port,
- unsigned char data)
-{
- outb(port, dev->io);
- outb(data, dev->io+1);
-}
-
-static void ite8709_wait_device(struct ite8709_device *dev)
-{
- int i = 0;
- /*
- * loop until device tells it's ready to continue
- * iterations count is usually ~750 but can sometimes achieve 13000
- */
- for (i = 0; i < 15000; i++) {
- udelay(2);
- if (ite8709_read(dev, ITE8709_MODE) == ITE8709_MODE_READY)
- break;
- }
-}
-
-static void ite8709_write_register(struct ite8709_device *dev,
- unsigned char reg_adr, unsigned char reg_value)
-{
- ite8709_wait_device(dev);
-
- ite8709_write(dev, ITE8709_REG_VAL, reg_value);
- ite8709_write(dev, ITE8709_REG_ADR, reg_adr);
- ite8709_write(dev, ITE8709_MODE, ITE8709_MODE_WRITE);
-}
-
-static void ite8709_init_hardware(struct ite8709_device *dev)
-{
- spin_lock_irq(&dev->hardware_lock);
- dev->device_busy = 1;
- spin_unlock_irq(&dev->hardware_lock);
-
- ite8709_write_register(dev, IT8512_REG_BDHR, (CFG_BDR >> 8) & 0xff);
- ite8709_write_register(dev, IT8512_REG_BDLR, CFG_BDR & 0xff);
- ite8709_write_register(dev, IT8512_REG_CFR, CFG_CR_FREQ);
- ite8709_write_register(dev, IT8512_REG_IER,
- IT8512_IER_IEC | IT8512_IER_RFOIE | IT8512_IER_RDAIE);
- ite8709_write_register(dev, IT8512_REG_RCR, CFG_DCR);
- ite8709_write_register(dev, IT8512_REG_MSTCR,
- CFG_FIFOTL | IT8512_MSTCR_FIFOCLR);
- ite8709_write_register(dev, IT8512_REG_RCR,
- IT8512_RCR_RXEN | IT8512_RCR_RXACT | CFG_DCR);
-
- spin_lock_irq(&dev->hardware_lock);
- dev->device_busy = 0;
- spin_unlock_irq(&dev->hardware_lock);
-
- tasklet_enable(&dev->tasklet);
-}
-
-static void ite8709_drop_hardware(struct ite8709_device *dev)
-{
- tasklet_disable(&dev->tasklet);
-
- spin_lock_irq(&dev->hardware_lock);
- dev->device_busy = 1;
- spin_unlock_irq(&dev->hardware_lock);
-
- ite8709_write_register(dev, IT8512_REG_RCR, 0);
- ite8709_write_register(dev, IT8512_REG_MSTCR,
- IT8512_MSTCR_RESET | IT8512_MSTCR_FIFOCLR);
-
- spin_lock_irq(&dev->hardware_lock);
- dev->device_busy = 0;
- spin_unlock_irq(&dev->hardware_lock);
-}
-
-static int ite8709_set_use_inc(void *data)
-{
- struct ite8709_device *dev;
- dev = data;
- if (dev->use_count == 0)
- ite8709_init_hardware(dev);
- dev->use_count++;
- return 0;
-}
-
-static void ite8709_set_use_dec(void *data)
-{
- struct ite8709_device *dev;
- dev = data;
- dev->use_count--;
- if (dev->use_count == 0)
- ite8709_drop_hardware(dev);
-}
-
-static void ite8709_add_read_queue(struct ite8709_device *dev, int flag,
- __u64 val)
-{
- int value;
-
- dprintk("add a %llu usec %s\n", val, flag ? "pulse" : "space");
-
- value = (val > PULSE_MASK) ? PULSE_MASK : val;
- if (flag)
- value |= PULSE_BIT;
-
- if (!lirc_buffer_full(dev->driver.rbuf)) {
- lirc_buffer_write(dev->driver.rbuf, (void *) &value);
- wake_up(&dev->driver.rbuf->wait_poll);
- }
-}
-
-static irqreturn_t ite8709_interrupt(int irq, void *dev_id)
-{
- unsigned char data;
- int iir, rfsr, i;
- int fifo = 0;
- char bit;
- struct timeval curr_tv;
-
- /* Bit duration in microseconds */
- const unsigned long bit_duration = 1000000ul / (115200 / CFG_BDR);
-
- struct ite8709_device *dev;
- dev = dev_id;
-
- /*
- * If device is busy, we simply discard data because we are in one of
- * these two cases : shutting down or rearming the device, so this
- * doesn't really matter and this avoids waiting too long in IRQ ctx
- */
- spin_lock(&dev->hardware_lock);
- if (dev->device_busy) {
- spin_unlock(&dev->hardware_lock);
- return IRQ_RETVAL(IRQ_HANDLED);
- }
-
- iir = ite8709_read(dev, ITE8709_IIR);
-
- switch (iir) {
- case ITE8709_IIR_RFOI:
- dprintk("fifo overrun, scheduling forced rearm just in case\n");
- dev->force_rearm = 1;
- tasklet_schedule(&dev->tasklet);
- spin_unlock(&dev->hardware_lock);
- return IRQ_RETVAL(IRQ_HANDLED);
-
- case ITE8709_IIR_RDAI:
- rfsr = ite8709_read(dev, ITE8709_RFSR);
- fifo = rfsr & ITE8709_RFSR_MASK;
- if (fifo > 32)
- fifo = 32;
- dprintk("iir: 0x%x rfsr: 0x%x fifo: %d\n", iir, rfsr, fifo);
-
- if (dev->rearmed) {
- do_gettimeofday(&curr_tv);
- dev->acc_space += 1000000ull
- * (curr_tv.tv_sec - dev->last_tv.tv_sec)
- + (curr_tv.tv_usec - dev->last_tv.tv_usec);
- dev->rearmed = 0;
- }
- for (i = 0; i < fifo; i++) {
- data = ite8709_read(dev, i+ITE8709_FIFO_START);
- data = ~data;
- /* Loop through */
- for (bit = 0; bit < 8; ++bit) {
- if ((data >> bit) & 1) {
- dev->acc_pulse += bit_duration;
- if (dev->lastbit == 0) {
- ite8709_add_read_queue(dev, 0,
- dev->acc_space);
- dev->acc_space = 0;
- }
- } else {
- dev->acc_space += bit_duration;
- if (dev->lastbit == 1) {
- ite8709_add_read_queue(dev, 1,
- dev->acc_pulse);
- dev->acc_pulse = 0;
- }
- }
- dev->lastbit = (data >> bit) & 1;
- }
- }
- ite8709_write(dev, ITE8709_RFSR, 0);
-
- if (dev->acc_space > CFG_TIMEOUT) {
- dprintk("scheduling rearm IRQ\n");
- do_gettimeofday(&dev->last_tv);
- dev->force_rearm = 0;
- tasklet_schedule(&dev->tasklet);
- }
-
- spin_unlock(&dev->hardware_lock);
- return IRQ_RETVAL(IRQ_HANDLED);
-
- default:
- /* not our irq */
- dprintk("unknown IRQ (shouldn't happen) !!\n");
- spin_unlock(&dev->hardware_lock);
- return IRQ_RETVAL(IRQ_NONE);
- }
-}
-
-static void ite8709_rearm_irq(unsigned long data)
-{
- struct ite8709_device *dev;
- unsigned long flags;
- dev = (struct ite8709_device *) data;
-
- spin_lock_irqsave(&dev->hardware_lock, flags);
- dev->device_busy = 1;
- spin_unlock_irqrestore(&dev->hardware_lock, flags);
-
- if (dev->force_rearm || dev->acc_space > CFG_TIMEOUT) {
- dprintk("rearming IRQ\n");
- ite8709_write_register(dev, IT8512_REG_RCR,
- IT8512_RCR_RXACT | CFG_DCR);
- ite8709_write_register(dev, IT8512_REG_MSTCR,
- CFG_FIFOTL | IT8512_MSTCR_FIFOCLR);
- ite8709_write_register(dev, IT8512_REG_RCR,
- IT8512_RCR_RXEN | IT8512_RCR_RXACT | CFG_DCR);
- if (!dev->force_rearm)
- dev->rearmed = 1;
- dev->force_rearm = 0;
- }
-
- spin_lock_irqsave(&dev->hardware_lock, flags);
- dev->device_busy = 0;
- spin_unlock_irqrestore(&dev->hardware_lock, flags);
-}
-
-static int ite8709_cleanup(struct ite8709_device *dev, int stage, int errno,
- char *msg)
-{
- if (msg != NULL)
- printk(KERN_ERR LIRC_DRIVER_NAME ": %s\n", msg);
-
- switch (stage) {
- case 6:
- if (dev->use_count > 0)
- ite8709_drop_hardware(dev);
- case 5:
- free_irq(dev->irq, dev);
- case 4:
- release_region(dev->io, 2);
- case 3:
- lirc_unregister_driver(dev->driver.minor);
- case 2:
- lirc_buffer_free(dev->driver.rbuf);
- kfree(dev->driver.rbuf);
- case 1:
- kfree(dev);
- case 0:
- ;
- }
-
- return errno;
-}
-
-static int __devinit ite8709_pnp_probe(struct pnp_dev *dev,
- const struct pnp_device_id *dev_id)
-{
- struct lirc_driver *driver;
- struct ite8709_device *ite8709_dev;
- int ret;
-
- /* Check resources validity */
- if (!pnp_irq_valid(dev, 0))
- return ite8709_cleanup(NULL, 0, -ENODEV, "invalid IRQ");
- if (!pnp_port_valid(dev, 2))
- return ite8709_cleanup(NULL, 0, -ENODEV, "invalid IO port");
-
- /* Allocate memory for device struct */
- ite8709_dev = kzalloc(sizeof(struct ite8709_device), GFP_KERNEL);
- if (ite8709_dev == NULL)
- return ite8709_cleanup(NULL, 0, -ENOMEM, "kzalloc failed");
- pnp_set_drvdata(dev, ite8709_dev);
-
- /* Initialize device struct */
- ite8709_dev->use_count = 0;
- ite8709_dev->irq = pnp_irq(dev, 0);
- ite8709_dev->io = pnp_port_start(dev, 2);
- ite8709_dev->hardware_lock =
- __SPIN_LOCK_UNLOCKED(ite8709_dev->hardware_lock);
- ite8709_dev->acc_pulse = 0;
- ite8709_dev->acc_space = 0;
- ite8709_dev->lastbit = 0;
- do_gettimeofday(&ite8709_dev->last_tv);
- tasklet_init(&ite8709_dev->tasklet, ite8709_rearm_irq,
- (long) ite8709_dev);
- ite8709_dev->force_rearm = 0;
- ite8709_dev->rearmed = 0;
- ite8709_dev->device_busy = 0;
-
- /* Initialize driver struct */
- driver = &ite8709_dev->driver;
- strcpy(driver->name, LIRC_DRIVER_NAME);
- driver->minor = -1;
- driver->code_length = sizeof(int) * 8;
- driver->sample_rate = 0;
- driver->features = LIRC_CAN_REC_MODE2;
- driver->data = ite8709_dev;
- driver->add_to_buf = NULL;
- driver->set_use_inc = ite8709_set_use_inc;
- driver->set_use_dec = ite8709_set_use_dec;
- driver->dev = &dev->dev;
- driver->owner = THIS_MODULE;
-
- /* Initialize LIRC buffer */
- driver->rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
- if (!driver->rbuf)
- return ite8709_cleanup(ite8709_dev, 1, -ENOMEM,
- "can't allocate lirc_buffer");
- if (lirc_buffer_init(driver->rbuf, BUF_CHUNK_SIZE, BUF_SIZE))
- return ite8709_cleanup(ite8709_dev, 1, -ENOMEM,
- "lirc_buffer_init() failed");
-
- /* Register LIRC driver */
- ret = lirc_register_driver(driver);
- if (ret < 0)
- return ite8709_cleanup(ite8709_dev, 2, ret,
- "lirc_register_driver() failed");
-
- /* Reserve I/O port access */
- if (!request_region(ite8709_dev->io, 2, LIRC_DRIVER_NAME))
- return ite8709_cleanup(ite8709_dev, 3, -EBUSY,
- "i/o port already in use");
-
- /* Reserve IRQ line */
- ret = request_irq(ite8709_dev->irq, ite8709_interrupt, 0,
- LIRC_DRIVER_NAME, ite8709_dev);
- if (ret < 0)
- return ite8709_cleanup(ite8709_dev, 4, ret,
- "IRQ already in use");
-
- /* Initialize hardware */
- ite8709_drop_hardware(ite8709_dev); /* Shutdown hw until first use */
-
- printk(KERN_INFO LIRC_DRIVER_NAME ": device found : irq=%d io=0x%x\n",
- ite8709_dev->irq, ite8709_dev->io);
-
- return 0;
-}
-
-static void __devexit ite8709_pnp_remove(struct pnp_dev *dev)
-{
- struct ite8709_device *ite8709_dev;
- ite8709_dev = pnp_get_drvdata(dev);
-
- ite8709_cleanup(ite8709_dev, 6, 0, NULL);
-
- printk(KERN_INFO LIRC_DRIVER_NAME ": device removed\n");
-}
-
-#ifdef CONFIG_PM
-static int ite8709_pnp_suspend(struct pnp_dev *dev, pm_message_t state)
-{
- struct ite8709_device *ite8709_dev;
- ite8709_dev = pnp_get_drvdata(dev);
-
- if (ite8709_dev->use_count > 0)
- ite8709_drop_hardware(ite8709_dev);
-
- return 0;
-}
-
-static int ite8709_pnp_resume(struct pnp_dev *dev)
-{
- struct ite8709_device *ite8709_dev;
- ite8709_dev = pnp_get_drvdata(dev);
-
- if (ite8709_dev->use_count > 0)
- ite8709_init_hardware(ite8709_dev);
-
- return 0;
-}
-#else
-#define ite8709_pnp_suspend NULL
-#define ite8709_pnp_resume NULL
-#endif
-
-static const struct pnp_device_id pnp_dev_table[] = {
- {"ITE8709", 0},
- {}
-};
-
-MODULE_DEVICE_TABLE(pnp, pnp_dev_table);
-
-static struct pnp_driver ite8709_pnp_driver = {
- .name = LIRC_DRIVER_NAME,
- .probe = ite8709_pnp_probe,
- .remove = __devexit_p(ite8709_pnp_remove),
- .suspend = ite8709_pnp_suspend,
- .resume = ite8709_pnp_resume,
- .id_table = pnp_dev_table,
-};
-
-static int __init ite8709_init_module(void)
-{
- return pnp_register_driver(&ite8709_pnp_driver);
-}
-module_init(ite8709_init_module);
-
-static void __exit ite8709_cleanup_module(void)
-{
- pnp_unregister_driver(&ite8709_pnp_driver);
-}
-module_exit(ite8709_cleanup_module);
-
-MODULE_DESCRIPTION("LIRC driver for ITE8709 CIR port");
-MODULE_AUTHOR("Grégory Lardière");
-MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Enable debugging messages");