/*
* lirc_serial.c
*
* lirc_serial - Device driver that records pulse- and pause-lengths
* (space-lengths) between DDCD event on a serial port.
*
* Copyright (C) 1996,97 Ralph Metzler <rjkm@thp.uni-koeln.de>
* Copyright (C) 1998 Trent Piepho <xyzzy@u.washington.edu>
* Copyright (C) 1998 Ben Pfaff <blp@gnu.org>
* Copyright (C) 1999 Christoph Bartelmus <lirc@bartelmus.de>
* Copyright (C) 2007 Andrei Tanas <andrei@tanas.ca> (suspend/resume support)
* 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
*
*/
/*
* Steve's changes to improve transmission fidelity:
* - for systems with the rdtsc instruction and the clock counter, a
* send_pule that times the pulses directly using the counter.
* This means that the LIRC_SERIAL_TRANSMITTER_LATENCY fudge is
* not needed. Measurement shows very stable waveform, even where
* PCI activity slows the access to the UART, which trips up other
* versions.
* - For other system, non-integer-microsecond pulse/space lengths,
* done using fixed point binary. So, much more accurate carrier
* frequency.
* - fine tuned transmitter latency, taking advantage of fractional
* microseconds in previous change
* - Fixed bug in the way transmitter latency was accounted for by
* tuning the pulse lengths down - the send_pulse routine ignored
* this overhead as it timed the overall pulse length - so the
* pulse frequency was right but overall pulse length was too
* long. Fixed by accounting for latency on each pulse/space
* iteration.
*
* Steve Davies <steve@daviesfam.org> July 2001
*/
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/serial_reg.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 <linux/platform_device.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/fcntl.h>
#include <linux/spinlock.h>
#ifdef CONFIG_LIRC_SERIAL_NSLU2
#include <asm/hardware.h>
#endif
/* From Intel IXP42X Developer's Manual (#252480-005): */
/* ftp://download.intel.com/design/network/manuals/25248005.pdf */
#define UART_IE_IXP42X_UUE 0x40 /* IXP42X UART Unit enable */
#define UART_IE_IXP42X_RTOIE 0x10 /* IXP42X Receiver Data Timeout int.enable */
#include <media/lirc.h>
#include <media/lirc_dev.h>
#define LIRC_DRIVER_NAME "lirc_serial"
struct lirc_serial {
int signal_pin;
int signal_pin_change;
u8 on;
u8 off;
long (*send_pulse)(unsigned long length);
void (*send_space)(long length);
int features;
spinlock_t lock;
};
#define LIRC_HOMEBREW 0
#define LIRC_IRDEO 1
#define LIRC_IRDEO_REMOTE 2
#define LIRC_ANIMAX 3
#define LIRC_IGOR 4
#define LIRC_NSLU2 5
/*** module parameters ***/
static int type;
static int io;
static int irq;
static bool iommap;
static int ioshift;
static bool softcarrier = 1;
static bool share_irq;
static bool debug;
static int sense = -1; /* -1 = auto, 0 = active high, 1 = active low */
static bool txsense; /* 0 = active high, 1 = active low */
#define dprintk(fmt, args...) \
do { \
if (debug) \
printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \
fmt, ## args); \
} while (0)
/* forward declarations */
static long send_pulse_irdeo(unsigned long length);
static long