nuvoton-cir.h 11.5 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421
/*
 * Driver for Nuvoton Technology Corporation w83667hg/w83677hg-i CIR
 *
 * Copyright (C) 2010 Jarod Wilson <jarod@redhat.com>
 * Copyright (C) 2009 Nuvoton PS Team
 *
 * Special thanks to Nuvoton for providing hardware, spec sheets and
 * sample code upon which portions of this driver are based. Indirect
 * thanks also to Maxim Levitsky, whose ene_ir driver this driver is
 * modeled after.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA
 */

#include <linux/spinlock.h>
#include <linux/ioctl.h>

/* platform driver name to register */
#define NVT_DRIVER_NAME "nuvoton-cir"

/* debugging module parameter */
static int debug;


#define nvt_pr(level, text, ...) \
	printk(level KBUILD_MODNAME ": " text, ## __VA_ARGS__)

#define nvt_dbg(text, ...) \
	if (debug) \
		printk(KERN_DEBUG \
			KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__)

#define nvt_dbg_verbose(text, ...) \
	if (debug > 1) \
		printk(KERN_DEBUG \
			KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__)

#define nvt_dbg_wake(text, ...) \
	if (debug > 2) \
		printk(KERN_DEBUG \
			KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__)


/*
 * Original lirc driver said min value of 76, and recommended value of 256
 * for the buffer length, but then used 2048. Never mind that the size of the
 * RX FIFO is 32 bytes... So I'm using 32 for RX and 256 for TX atm, but I'm
 * not sure if maybe that TX value is off by a factor of 8 (bits vs. bytes),
 * and I don't have TX-capable hardware to test/debug on...
 */
#define TX_BUF_LEN 256
#define RX_BUF_LEN 32

struct nvt_dev {
	struct pnp_dev *pdev;
	struct rc_dev *rdev;
	struct ir_raw_event rawir;

	spinlock_t nvt_lock;
	bool in_use;

	/* for rx */
	u8 buf[RX_BUF_LEN];
	unsigned int pkts;

	struct {
		spinlock_t lock;
		u8 buf[TX_BUF_LEN];
		unsigned int buf_count;
		unsigned int cur_buf_num;
		wait_queue_head_t queue;
		u8 tx_state;
	} tx;

	/* EFER Config register index/data pair */
	u8 cr_efir;
	u8 cr_efdr;

	/* hardware I/O settings */
	unsigned long cir_addr;
	unsigned long cir_wake_addr;
	int cir_irq;
	int cir_wake_irq;

	/* hardware id */
	u8 chip_major;
	u8 chip_minor;

	/* hardware features */
	bool hw_learning_capable;
	bool hw_tx_capable;

	/* rx settings */
	bool learning_enabled;
	bool carrier_detect_enabled;

	/* track cir wake state */
	u8 wake_state;
	/* for study */
	u8 study_state;
	/* carrier period = 1 / frequency */
	u32 carrier;
};

/* study states */
#define ST_STUDY_NONE      0x0
#define ST_STUDY_START     0x1
#define ST_STUDY_CARRIER   0x2
#define ST_STUDY_ALL_RECV  0x4

/* wake states */
#define ST_WAKE_NONE	0x0
#define ST_WAKE_START	0x1
#define ST_WAKE_FINISH	0x2

/* receive states */
#define ST_RX_WAIT_7F		0x1
#define ST_RX_WAIT_HEAD		0x2
#define ST_RX_WAIT_SILENT_END	0x4

/* send states */
#define ST_TX_NONE	0x0
#define ST_TX_REQUEST	0x2
#define ST_TX_REPLY	0x4

/* buffer packet constants */
#define BUF_PULSE_BIT	0x80
#define BUF_LEN_MASK	0x7f
#define BUF_REPEAT_BYTE	0x70
#define BUF_REPEAT_MASK	0xf0

/* CIR settings */

/* total length of CIR and CIR WAKE */
#define CIR_IOREG_LENGTH	0x0f

/* RX limit length, 8 high bits for SLCH, 8 low bits for SLCL (0x7d0 = 2000) */
#define CIR_RX_LIMIT_COUNT	0x7d0

/* CIR Regs */
#define CIR_IRCON	0x00
#define CIR_IRSTS	0x01
#define CIR_IREN	0x02
#define CIR_RXFCONT	0x03
#define CIR_CP		0x04
#define CIR_CC		0x05
#define CIR_SLCH	0x06
#define CIR_SLCL	0x07
#define CIR_FIFOCON	0x08
#define CIR_IRFIFOSTS	0x09
#define CIR_SRXFIFO	0x0a
#define CIR_TXFCONT	0x0b
#define CIR_STXFIFO	0x0c
#define CIR_FCCH	0x0d
#define CIR_FCCL	0x0e
#define CIR_IRFSM	0x0f

/* CIR IRCON settings */
#define CIR_IRCON_RECV	 0x80
#define CIR_IRCON_WIREN	 0x40
#define CIR_IRCON_TXEN	 0x20
#define CIR_IRCON_RXEN	 0x10
#define CIR_IRCON_WRXINV 0x08
#define CIR_IRCON_RXINV	 0x04

#define CIR_IRCON_SAMPLE_PERIOD_SEL_1	0x00
#define CIR_IRCON_SAMPLE_PERIOD_SEL_25	0x01
#define CIR_IRCON_SAMPLE_PERIOD_SEL_50	0x02
#define CIR_IRCON_SAMPLE_PERIOD_SEL_100	0x03

/* FIXME: make this a runtime option */
/* select sample period as 50us */
#define CIR_IRCON_SAMPLE_PERIOD_SEL	CIR_IRCON_SAMPLE_PERIOD_SEL_50

/* CIR IRSTS settings */
#define CIR_IRSTS_RDR	0x80
#define CIR_IRSTS_RTR	0x40
#define CIR_IRSTS_PE	0x20
#define CIR_IRSTS_RFO	0x10
#define CIR_IRSTS_TE	0x08
#define CIR_IRSTS_TTR	0x04
#define CIR_IRSTS_TFU	0x02
#define CIR_IRSTS_GH	0x01

/* CIR IREN settings */
#define CIR_IREN_RDR	0x80
#define CIR_IREN_RTR	0x40
#define CIR_IREN_PE	0x20
#define CIR_IREN_RFO	0x10
#define CIR_IREN_TE	0x08
#define CIR_IREN_TTR	0x04
#define CIR_IREN_TFU	0x02
#define CIR_IREN_GH	0x01

/* CIR FIFOCON settings */
#define CIR_FIFOCON_TXFIFOCLR		0x80

#define CIR_FIFOCON_TX_TRIGGER_LEV_31	0x00
#define CIR_FIFOCON_TX_TRIGGER_LEV_24	0x10
#define CIR_FIFOCON_TX_TRIGGER_LEV_16	0x20
#define CIR_FIFOCON_TX_TRIGGER_LEV_8	0x30

/* FIXME: make this a runtime option */
/* select TX trigger level as 16 */
#define CIR_FIFOCON_TX_TRIGGER_LEV	CIR_FIFOCON_TX_TRIGGER_LEV_16

#define CIR_FIFOCON_RXFIFOCLR		0x08

#define CIR_FIFOCON_RX_TRIGGER_LEV_1	0x00
#define CIR_FIFOCON_RX_TRIGGER_LEV_8	0x01
#define CIR_FIFOCON_RX_TRIGGER_LEV_16	0x02
#define CIR_FIFOCON_RX_TRIGGER_LEV_24	0x03

/* FIXME: make this a runtime option */
/* select RX trigger level as 24 */
#define CIR_FIFOCON_RX_TRIGGER_LEV	CIR_FIFOCON_RX_TRIGGER_LEV_24

/* CIR IRFIFOSTS settings */
#define CIR_IRFIFOSTS_IR_PENDING	0x80
#define CIR_IRFIFOSTS_RX_GS		0x40
#define CIR_IRFIFOSTS_RX_FTA		0x20
#define CIR_IRFIFOSTS_RX_EMPTY		0x10
#define CIR_IRFIFOSTS_RX_FULL		0x08
#define CIR_IRFIFOSTS_TX_FTA		0x04
#define CIR_IRFIFOSTS_TX_EMPTY		0x02
#define CIR_IRFIFOSTS_TX_FULL		0x01


/* CIR WAKE UP Regs */
#define CIR_WAKE_IRCON			0x00
#define CIR_WAKE_IRSTS			0x01
#define CIR_WAKE_IREN			0x02
#define CIR_WAKE_FIFO_CMP_DEEP		0x03
#define CIR_WAKE_FIFO_CMP_TOL		0x04
#define CIR_WAKE_FIFO_COUNT		0x05
#define CIR_WAKE_SLCH			0x06
#define CIR_WAKE_SLCL			0x07
#define CIR_WAKE_FIFOCON		0x08
#define CIR_WAKE_SRXFSTS		0x09
#define CIR_WAKE_SAMPLE_RX_FIFO		0x0a
#define CIR_WAKE_WR_FIFO_DATA		0x0b
#define CIR_WAKE_RD_FIFO_ONLY		0x0c
#define CIR_WAKE_RD_FIFO_ONLY_IDX	0x0d
#define CIR_WAKE_FIFO_IGNORE		0x0e
#define CIR_WAKE_IRFSM			0x0f

/* CIR WAKE UP IRCON settings */
#define CIR_WAKE_IRCON_DEC_RST		0x80
#define CIR_WAKE_IRCON_MODE1		0x40
#define CIR_WAKE_IRCON_MODE0		0x20
#define CIR_WAKE_IRCON_RXEN		0x10
#define CIR_WAKE_IRCON_R		0x08
#define CIR_WAKE_IRCON_RXINV		0x04

/* FIXME/jarod: make this a runtime option */
/* select a same sample period like cir register */
#define CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL	CIR_IRCON_SAMPLE_PERIOD_SEL_50

/* CIR WAKE IRSTS Bits */
#define CIR_WAKE_IRSTS_RDR		0x80
#define CIR_WAKE_IRSTS_RTR		0x40
#define CIR_WAKE_IRSTS_PE		0x20
#define CIR_WAKE_IRSTS_RFO		0x10
#define CIR_WAKE_IRSTS_GH		0x08
#define CIR_WAKE_IRSTS_IR_PENDING	0x01

/* CIR WAKE UP IREN Bits */
#define CIR_WAKE_IREN_RDR		0x80
#define CIR_WAKE_IREN_RTR		0x40
#define CIR_WAKE_IREN_PE		0x20
#define CIR_WAKE_IREN_RFO		0x10
#define CIR_WAKE_IREN_TE		0x08
#define CIR_WAKE_IREN_TTR		0x04
#define CIR_WAKE_IREN_TFU		0x02
#define CIR_WAKE_IREN_GH		0x01

/* CIR WAKE FIFOCON settings */
#define CIR_WAKE_FIFOCON_RXFIFOCLR	0x08

#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_67	0x00
#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_66	0x01
#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_65	0x02
#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_64	0x03

/* FIXME: make this a runtime option */
/* select WAKE UP RX trigger level as 67 */
#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV	CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_67

/* CIR WAKE SRXFSTS settings */
#define CIR_WAKE_IRFIFOSTS_RX_GS	0x80
#define CIR_WAKE_IRFIFOSTS_RX_FTA	0x40
#define CIR_WAKE_IRFIFOSTS_RX_EMPTY	0x20
#define CIR_WAKE_IRFIFOSTS_RX_FULL	0x10

/*
 * The CIR Wake FIFO buffer is 67 bytes long, but the stock remote wakes
 * the system comparing only 65 bytes (fails with this set to 67)
 */
#define CIR_WAKE_FIFO_CMP_BYTES		65
/* CIR Wake byte comparison tolerance */
#define CIR_WAKE_CMP_TOLERANCE		5

/*
 * Extended Function Enable Registers:
 *  Extended Function Index Register
 *  Extended Function Data Register
 */
#define CR_EFIR			0x2e
#define CR_EFDR			0x2f

/* Possible alternate EFER values, depends on how the chip is wired */
#define CR_EFIR2		0x4e
#define CR_EFDR2		0x4f

/* Extended Function Mode enable/disable magic values */
#define EFER_EFM_ENABLE		0x87
#define EFER_EFM_DISABLE	0xaa

/* Chip IDs found in CR_CHIP_ID_{HI,LO} */
#define CHIP_ID_HIGH_667	0xa5
#define CHIP_ID_HIGH_677B	0xb4
#define CHIP_ID_HIGH_677C	0xc3
#define CHIP_ID_LOW_667		0x13
#define CHIP_ID_LOW_677B2	0x72
#define CHIP_ID_LOW_677B3	0x73
#define CHIP_ID_LOW_677C	0x33

/* Config regs we need to care about */
#define CR_SOFTWARE_RESET	0x02
#define CR_LOGICAL_DEV_SEL	0x07
#define CR_CHIP_ID_HI		0x20
#define CR_CHIP_ID_LO		0x21
#define CR_DEV_POWER_DOWN	0x22 /* bit 2 is CIR power, default power on */
#define CR_OUTPUT_PIN_SEL	0x27
#define CR_MULTIFUNC_PIN_SEL	0x2c
#define CR_LOGICAL_DEV_EN	0x30 /* valid for all logical devices */
/* next three regs valid for both the CIR and CIR_WAKE logical devices */
#define CR_CIR_BASE_ADDR_HI	0x60
#define CR_CIR_BASE_ADDR_LO	0x61
#define CR_CIR_IRQ_RSRC		0x70
/* next three regs valid only for ACPI logical dev */
#define CR_ACPI_CIR_WAKE	0xe0
#define CR_ACPI_IRQ_EVENTS	0xf6
#define CR_ACPI_IRQ_EVENTS2	0xf7

/* Logical devices that we need to care about */
#define LOGICAL_DEV_LPT		0x01
#define LOGICAL_DEV_CIR		0x06
#define LOGICAL_DEV_ACPI	0x0a
#define LOGICAL_DEV_CIR_WAKE	0x0e

#define LOGICAL_DEV_DISABLE	0x00
#define LOGICAL_DEV_ENABLE	0x01

#define CIR_WAKE_ENABLE_BIT	0x08
#define CIR_INTR_MOUSE_IRQ_BIT	0x80
#define PME_INTR_CIR_PASS_BIT	0x08

/* w83677hg CIR pin config */
#define OUTPUT_PIN_SEL_MASK	0xbc
#define OUTPUT_ENABLE_CIR	0x01 /* Pin95=CIRRX, Pin96=CIRTX1 */
#define OUTPUT_ENABLE_CIRWB	0x40 /* enable wide-band sensor */

/* w83667hg CIR pin config */
#define MULTIFUNC_PIN_SEL_MASK	0x1f
#define MULTIFUNC_ENABLE_CIR	0x80 /* Pin75=CIRRX, Pin76=CIRTX1 */
#define MULTIFUNC_ENABLE_CIRWB	0x20 /* enable wide-band sensor */

/* MCE CIR signal length, related on sample period */

/* MCE CIR controller signal length: about 43ms
 * 43ms / 50us (sample period) * 0.85 (inaccuracy)
 */
#define CONTROLLER_BUF_LEN_MIN 830

/* MCE CIR keyboard signal length: about 26ms
 * 26ms / 50us (sample period) * 0.85 (inaccuracy)
 */
#define KEYBOARD_BUF_LEN_MAX 650
#define KEYBOARD_BUF_LEN_MIN 610

/* MCE CIR mouse signal length: about 24ms
 * 24ms / 50us (sample period) * 0.85 (inaccuracy)
 */
#define MOUSE_BUF_LEN_MIN 565

#define CIR_SAMPLE_PERIOD 50
#define CIR_SAMPLE_LOW_INACCURACY 0.85

/* MAX silence time that driver will sent to lirc */
#define MAX_SILENCE_TIME 60000

#if CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_100
#define SAMPLE_PERIOD 100

#elif CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_50
#define SAMPLE_PERIOD 50

#elif CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_25
#define SAMPLE_PERIOD 25

#else
#define SAMPLE_PERIOD 1
#endif

/* as VISTA MCE definition, valid carrier value */
#define MAX_CARRIER 60000
#define MIN_CARRIER 30000