summaryrefslogtreecommitdiff
path: root/drivers/media/rc/nuvoton-cir.h
blob: ed7d93beaa280a2f11e46614a08e0c0d274b9384 (plain)
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
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * 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.
 */

#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_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__)


#define RX_BUF_LEN 32

#define SIO_ID_MASK 0xfff0

enum nvt_chip_ver {
	NVT_UNKNOWN	= 0,
	NVT_W83667HG	= 0xa510,
	NVT_6775F	= 0xb470,
	NVT_6776F	= 0xc330,
	NVT_6779D	= 0xc560,
	NVT_INVALID	= 0xffff,
};

struct nvt_chip {
	const char *name;
	enum nvt_chip_ver chip_ver;
};

struct nvt_dev {
	struct rc_dev *rdev;

	spinlock_t lock;

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

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

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

	enum nvt_chip_ver chip_ver;
	/* hardware id */
	u8 chip_major;
	u8 chip_minor;

	/* carrier period = 1 / frequency */
	u32 carrier;
};

/* 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 */
#define CIR_RX_LIMIT_COUNT  (IR_DEFAULT_TIMEOUT / SAMPLE_PERIOD)

/* 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_GH		0x08

/* 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

/* 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 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

/* max wakeup sequence length */
#define WAKEUP_MAX_SIZE 65