Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/media/rc/fintek-cir.c
15111 views
1
/*
2
* Driver for Feature Integration Technology Inc. (aka Fintek) LPC CIR
3
*
4
* Copyright (C) 2011 Jarod Wilson <[email protected]>
5
*
6
* Special thanks to Fintek for providing hardware and spec sheets.
7
* This driver is based upon the nuvoton, ite and ene drivers for
8
* similar hardware.
9
*
10
* This program is free software; you can redistribute it and/or
11
* modify it under the terms of the GNU General Public License as
12
* published by the Free Software Foundation; either version 2 of the
13
* License, or (at your option) any later version.
14
*
15
* This program is distributed in the hope that it will be useful, but
16
* WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18
* General Public License for more details.
19
*
20
* You should have received a copy of the GNU General Public License
21
* along with this program; if not, write to the Free Software
22
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23
* USA
24
*/
25
26
#include <linux/kernel.h>
27
#include <linux/module.h>
28
#include <linux/pnp.h>
29
#include <linux/io.h>
30
#include <linux/interrupt.h>
31
#include <linux/sched.h>
32
#include <linux/slab.h>
33
#include <media/rc-core.h>
34
#include <linux/pci_ids.h>
35
36
#include "fintek-cir.h"
37
38
/* write val to config reg */
39
static inline void fintek_cr_write(struct fintek_dev *fintek, u8 val, u8 reg)
40
{
41
fit_dbg("%s: reg 0x%02x, val 0x%02x (ip/dp: %02x/%02x)",
42
__func__, reg, val, fintek->cr_ip, fintek->cr_dp);
43
outb(reg, fintek->cr_ip);
44
outb(val, fintek->cr_dp);
45
}
46
47
/* read val from config reg */
48
static inline u8 fintek_cr_read(struct fintek_dev *fintek, u8 reg)
49
{
50
u8 val;
51
52
outb(reg, fintek->cr_ip);
53
val = inb(fintek->cr_dp);
54
55
fit_dbg("%s: reg 0x%02x, val 0x%02x (ip/dp: %02x/%02x)",
56
__func__, reg, val, fintek->cr_ip, fintek->cr_dp);
57
return val;
58
}
59
60
/* update config register bit without changing other bits */
61
static inline void fintek_set_reg_bit(struct fintek_dev *fintek, u8 val, u8 reg)
62
{
63
u8 tmp = fintek_cr_read(fintek, reg) | val;
64
fintek_cr_write(fintek, tmp, reg);
65
}
66
67
/* clear config register bit without changing other bits */
68
static inline void fintek_clear_reg_bit(struct fintek_dev *fintek, u8 val, u8 reg)
69
{
70
u8 tmp = fintek_cr_read(fintek, reg) & ~val;
71
fintek_cr_write(fintek, tmp, reg);
72
}
73
74
/* enter config mode */
75
static inline void fintek_config_mode_enable(struct fintek_dev *fintek)
76
{
77
/* Enabling Config Mode explicitly requires writing 2x */
78
outb(CONFIG_REG_ENABLE, fintek->cr_ip);
79
outb(CONFIG_REG_ENABLE, fintek->cr_ip);
80
}
81
82
/* exit config mode */
83
static inline void fintek_config_mode_disable(struct fintek_dev *fintek)
84
{
85
outb(CONFIG_REG_DISABLE, fintek->cr_ip);
86
}
87
88
/*
89
* When you want to address a specific logical device, write its logical
90
* device number to GCR_LOGICAL_DEV_NO
91
*/
92
static inline void fintek_select_logical_dev(struct fintek_dev *fintek, u8 ldev)
93
{
94
fintek_cr_write(fintek, ldev, GCR_LOGICAL_DEV_NO);
95
}
96
97
/* write val to cir config register */
98
static inline void fintek_cir_reg_write(struct fintek_dev *fintek, u8 val, u8 offset)
99
{
100
outb(val, fintek->cir_addr + offset);
101
}
102
103
/* read val from cir config register */
104
static u8 fintek_cir_reg_read(struct fintek_dev *fintek, u8 offset)
105
{
106
u8 val;
107
108
val = inb(fintek->cir_addr + offset);
109
110
return val;
111
}
112
113
#define pr_reg(text, ...) \
114
printk(KERN_INFO KBUILD_MODNAME ": " text, ## __VA_ARGS__)
115
116
/* dump current cir register contents */
117
static void cir_dump_regs(struct fintek_dev *fintek)
118
{
119
fintek_config_mode_enable(fintek);
120
fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR);
121
122
pr_reg("%s: Dump CIR logical device registers:\n", FINTEK_DRIVER_NAME);
123
pr_reg(" * CR CIR BASE ADDR: 0x%x\n",
124
(fintek_cr_read(fintek, CIR_CR_BASE_ADDR_HI) << 8) |
125
fintek_cr_read(fintek, CIR_CR_BASE_ADDR_LO));
126
pr_reg(" * CR CIR IRQ NUM: 0x%x\n",
127
fintek_cr_read(fintek, CIR_CR_IRQ_SEL));
128
129
fintek_config_mode_disable(fintek);
130
131
pr_reg("%s: Dump CIR registers:\n", FINTEK_DRIVER_NAME);
132
pr_reg(" * STATUS: 0x%x\n", fintek_cir_reg_read(fintek, CIR_STATUS));
133
pr_reg(" * CONTROL: 0x%x\n", fintek_cir_reg_read(fintek, CIR_CONTROL));
134
pr_reg(" * RX_DATA: 0x%x\n", fintek_cir_reg_read(fintek, CIR_RX_DATA));
135
pr_reg(" * TX_CONTROL: 0x%x\n", fintek_cir_reg_read(fintek, CIR_TX_CONTROL));
136
pr_reg(" * TX_DATA: 0x%x\n", fintek_cir_reg_read(fintek, CIR_TX_DATA));
137
}
138
139
/* detect hardware features */
140
static int fintek_hw_detect(struct fintek_dev *fintek)
141
{
142
unsigned long flags;
143
u8 chip_major, chip_minor;
144
u8 vendor_major, vendor_minor;
145
u8 portsel, ir_class;
146
u16 vendor;
147
int ret = 0;
148
149
fintek_config_mode_enable(fintek);
150
151
/* Check if we're using config port 0x4e or 0x2e */
152
portsel = fintek_cr_read(fintek, GCR_CONFIG_PORT_SEL);
153
if (portsel == 0xff) {
154
fit_pr(KERN_INFO, "first portsel read was bunk, trying alt");
155
fintek_config_mode_disable(fintek);
156
fintek->cr_ip = CR_INDEX_PORT2;
157
fintek->cr_dp = CR_DATA_PORT2;
158
fintek_config_mode_enable(fintek);
159
portsel = fintek_cr_read(fintek, GCR_CONFIG_PORT_SEL);
160
}
161
fit_dbg("portsel reg: 0x%02x", portsel);
162
163
ir_class = fintek_cir_reg_read(fintek, CIR_CR_CLASS);
164
fit_dbg("ir_class reg: 0x%02x", ir_class);
165
166
switch (ir_class) {
167
case CLASS_RX_2TX:
168
case CLASS_RX_1TX:
169
fintek->hw_tx_capable = true;
170
break;
171
case CLASS_RX_ONLY:
172
default:
173
fintek->hw_tx_capable = false;
174
break;
175
}
176
177
chip_major = fintek_cr_read(fintek, GCR_CHIP_ID_HI);
178
chip_minor = fintek_cr_read(fintek, GCR_CHIP_ID_LO);
179
180
vendor_major = fintek_cr_read(fintek, GCR_VENDOR_ID_HI);
181
vendor_minor = fintek_cr_read(fintek, GCR_VENDOR_ID_LO);
182
vendor = vendor_major << 8 | vendor_minor;
183
184
if (vendor != VENDOR_ID_FINTEK)
185
fit_pr(KERN_WARNING, "Unknown vendor ID: 0x%04x", vendor);
186
else
187
fit_dbg("Read Fintek vendor ID from chip");
188
189
fintek_config_mode_disable(fintek);
190
191
spin_lock_irqsave(&fintek->fintek_lock, flags);
192
fintek->chip_major = chip_major;
193
fintek->chip_minor = chip_minor;
194
fintek->chip_vendor = vendor;
195
spin_unlock_irqrestore(&fintek->fintek_lock, flags);
196
197
return ret;
198
}
199
200
static void fintek_cir_ldev_init(struct fintek_dev *fintek)
201
{
202
/* Select CIR logical device and enable */
203
fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR);
204
fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN);
205
206
/* Write allocated CIR address and IRQ information to hardware */
207
fintek_cr_write(fintek, fintek->cir_addr >> 8, CIR_CR_BASE_ADDR_HI);
208
fintek_cr_write(fintek, fintek->cir_addr & 0xff, CIR_CR_BASE_ADDR_LO);
209
210
fintek_cr_write(fintek, fintek->cir_irq, CIR_CR_IRQ_SEL);
211
212
fit_dbg("CIR initialized, base io address: 0x%lx, irq: %d (len: %d)",
213
fintek->cir_addr, fintek->cir_irq, fintek->cir_port_len);
214
}
215
216
/* enable CIR interrupts */
217
static void fintek_enable_cir_irq(struct fintek_dev *fintek)
218
{
219
fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_EN, CIR_STATUS);
220
}
221
222
static void fintek_cir_regs_init(struct fintek_dev *fintek)
223
{
224
/* clear any and all stray interrupts */
225
fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS);
226
227
/* and finally, enable interrupts */
228
fintek_enable_cir_irq(fintek);
229
}
230
231
static void fintek_enable_wake(struct fintek_dev *fintek)
232
{
233
fintek_config_mode_enable(fintek);
234
fintek_select_logical_dev(fintek, LOGICAL_DEV_ACPI);
235
236
/* Allow CIR PME's to wake system */
237
fintek_set_reg_bit(fintek, ACPI_WAKE_EN_CIR_BIT, LDEV_ACPI_WAKE_EN_REG);
238
/* Enable CIR PME's */
239
fintek_set_reg_bit(fintek, ACPI_PME_CIR_BIT, LDEV_ACPI_PME_EN_REG);
240
/* Clear CIR PME status register */
241
fintek_set_reg_bit(fintek, ACPI_PME_CIR_BIT, LDEV_ACPI_PME_CLR_REG);
242
/* Save state */
243
fintek_set_reg_bit(fintek, ACPI_STATE_CIR_BIT, LDEV_ACPI_STATE_REG);
244
245
fintek_config_mode_disable(fintek);
246
}
247
248
static int fintek_cmdsize(u8 cmd, u8 subcmd)
249
{
250
int datasize = 0;
251
252
switch (cmd) {
253
case BUF_COMMAND_NULL:
254
if (subcmd == BUF_HW_CMD_HEADER)
255
datasize = 1;
256
break;
257
case BUF_HW_CMD_HEADER:
258
if (subcmd == BUF_CMD_G_REVISION)
259
datasize = 2;
260
break;
261
case BUF_COMMAND_HEADER:
262
switch (subcmd) {
263
case BUF_CMD_S_CARRIER:
264
case BUF_CMD_S_TIMEOUT:
265
case BUF_RSP_PULSE_COUNT:
266
datasize = 2;
267
break;
268
case BUF_CMD_SIG_END:
269
case BUF_CMD_S_TXMASK:
270
case BUF_CMD_S_RXSENSOR:
271
datasize = 1;
272
break;
273
}
274
}
275
276
return datasize;
277
}
278
279
/* process ir data stored in driver buffer */
280
static void fintek_process_rx_ir_data(struct fintek_dev *fintek)
281
{
282
DEFINE_IR_RAW_EVENT(rawir);
283
u8 sample;
284
int i;
285
286
for (i = 0; i < fintek->pkts; i++) {
287
sample = fintek->buf[i];
288
switch (fintek->parser_state) {
289
case CMD_HEADER:
290
fintek->cmd = sample;
291
if ((fintek->cmd == BUF_COMMAND_HEADER) ||
292
((fintek->cmd & BUF_COMMAND_MASK) !=
293
BUF_PULSE_BIT)) {
294
fintek->parser_state = SUBCMD;
295
continue;
296
}
297
fintek->rem = (fintek->cmd & BUF_LEN_MASK);
298
fit_dbg("%s: rem: 0x%02x", __func__, fintek->rem);
299
if (fintek->rem)
300
fintek->parser_state = PARSE_IRDATA;
301
else
302
ir_raw_event_reset(fintek->rdev);
303
break;
304
case SUBCMD:
305
fintek->rem = fintek_cmdsize(fintek->cmd, sample);
306
fintek->parser_state = CMD_DATA;
307
break;
308
case CMD_DATA:
309
fintek->rem--;
310
break;
311
case PARSE_IRDATA:
312
fintek->rem--;
313
init_ir_raw_event(&rawir);
314
rawir.pulse = ((sample & BUF_PULSE_BIT) != 0);
315
rawir.duration = US_TO_NS((sample & BUF_SAMPLE_MASK)
316
* CIR_SAMPLE_PERIOD);
317
318
fit_dbg("Storing %s with duration %d",
319
rawir.pulse ? "pulse" : "space",
320
rawir.duration);
321
ir_raw_event_store_with_filter(fintek->rdev, &rawir);
322
break;
323
}
324
325
if ((fintek->parser_state != CMD_HEADER) && !fintek->rem)
326
fintek->parser_state = CMD_HEADER;
327
}
328
329
fintek->pkts = 0;
330
331
fit_dbg("Calling ir_raw_event_handle");
332
ir_raw_event_handle(fintek->rdev);
333
}
334
335
/* copy data from hardware rx register into driver buffer */
336
static void fintek_get_rx_ir_data(struct fintek_dev *fintek, u8 rx_irqs)
337
{
338
unsigned long flags;
339
u8 sample, status;
340
341
spin_lock_irqsave(&fintek->fintek_lock, flags);
342
343
/*
344
* We must read data from CIR_RX_DATA until the hardware IR buffer
345
* is empty and clears the RX_TIMEOUT and/or RX_RECEIVE flags in
346
* the CIR_STATUS register
347
*/
348
do {
349
sample = fintek_cir_reg_read(fintek, CIR_RX_DATA);
350
fit_dbg("%s: sample: 0x%02x", __func__, sample);
351
352
fintek->buf[fintek->pkts] = sample;
353
fintek->pkts++;
354
355
status = fintek_cir_reg_read(fintek, CIR_STATUS);
356
if (!(status & CIR_STATUS_IRQ_EN))
357
break;
358
} while (status & rx_irqs);
359
360
fintek_process_rx_ir_data(fintek);
361
362
spin_unlock_irqrestore(&fintek->fintek_lock, flags);
363
}
364
365
static void fintek_cir_log_irqs(u8 status)
366
{
367
fit_pr(KERN_INFO, "IRQ 0x%02x:%s%s%s%s%s", status,
368
status & CIR_STATUS_IRQ_EN ? " IRQEN" : "",
369
status & CIR_STATUS_TX_FINISH ? " TXF" : "",
370
status & CIR_STATUS_TX_UNDERRUN ? " TXU" : "",
371
status & CIR_STATUS_RX_TIMEOUT ? " RXTO" : "",
372
status & CIR_STATUS_RX_RECEIVE ? " RXOK" : "");
373
}
374
375
/* interrupt service routine for incoming and outgoing CIR data */
376
static irqreturn_t fintek_cir_isr(int irq, void *data)
377
{
378
struct fintek_dev *fintek = data;
379
u8 status, rx_irqs;
380
381
fit_dbg_verbose("%s firing", __func__);
382
383
fintek_config_mode_enable(fintek);
384
fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR);
385
fintek_config_mode_disable(fintek);
386
387
/*
388
* Get IR Status register contents. Write 1 to ack/clear
389
*
390
* bit: reg name - description
391
* 3: TX_FINISH - TX is finished
392
* 2: TX_UNDERRUN - TX underrun
393
* 1: RX_TIMEOUT - RX data timeout
394
* 0: RX_RECEIVE - RX data received
395
*/
396
status = fintek_cir_reg_read(fintek, CIR_STATUS);
397
if (!(status & CIR_STATUS_IRQ_MASK) || status == 0xff) {
398
fit_dbg_verbose("%s exiting, IRSTS 0x%02x", __func__, status);
399
fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS);
400
return IRQ_RETVAL(IRQ_NONE);
401
}
402
403
if (debug)
404
fintek_cir_log_irqs(status);
405
406
rx_irqs = status & (CIR_STATUS_RX_RECEIVE | CIR_STATUS_RX_TIMEOUT);
407
if (rx_irqs)
408
fintek_get_rx_ir_data(fintek, rx_irqs);
409
410
/* ack/clear all irq flags we've got */
411
fintek_cir_reg_write(fintek, status, CIR_STATUS);
412
413
fit_dbg_verbose("%s done", __func__);
414
return IRQ_RETVAL(IRQ_HANDLED);
415
}
416
417
static void fintek_enable_cir(struct fintek_dev *fintek)
418
{
419
/* set IRQ enabled */
420
fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_EN, CIR_STATUS);
421
422
fintek_config_mode_enable(fintek);
423
424
/* enable the CIR logical device */
425
fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR);
426
fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN);
427
428
fintek_config_mode_disable(fintek);
429
430
/* clear all pending interrupts */
431
fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS);
432
433
/* enable interrupts */
434
fintek_enable_cir_irq(fintek);
435
}
436
437
static void fintek_disable_cir(struct fintek_dev *fintek)
438
{
439
fintek_config_mode_enable(fintek);
440
441
/* disable the CIR logical device */
442
fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR);
443
fintek_cr_write(fintek, LOGICAL_DEV_DISABLE, CIR_CR_DEV_EN);
444
445
fintek_config_mode_disable(fintek);
446
}
447
448
static int fintek_open(struct rc_dev *dev)
449
{
450
struct fintek_dev *fintek = dev->priv;
451
unsigned long flags;
452
453
spin_lock_irqsave(&fintek->fintek_lock, flags);
454
fintek_enable_cir(fintek);
455
spin_unlock_irqrestore(&fintek->fintek_lock, flags);
456
457
return 0;
458
}
459
460
static void fintek_close(struct rc_dev *dev)
461
{
462
struct fintek_dev *fintek = dev->priv;
463
unsigned long flags;
464
465
spin_lock_irqsave(&fintek->fintek_lock, flags);
466
fintek_disable_cir(fintek);
467
spin_unlock_irqrestore(&fintek->fintek_lock, flags);
468
}
469
470
/* Allocate memory, probe hardware, and initialize everything */
471
static int fintek_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
472
{
473
struct fintek_dev *fintek;
474
struct rc_dev *rdev;
475
int ret = -ENOMEM;
476
477
fintek = kzalloc(sizeof(struct fintek_dev), GFP_KERNEL);
478
if (!fintek)
479
return ret;
480
481
/* input device for IR remote (and tx) */
482
rdev = rc_allocate_device();
483
if (!rdev)
484
goto failure;
485
486
ret = -ENODEV;
487
/* validate pnp resources */
488
if (!pnp_port_valid(pdev, 0)) {
489
dev_err(&pdev->dev, "IR PNP Port not valid!\n");
490
goto failure;
491
}
492
493
if (!pnp_irq_valid(pdev, 0)) {
494
dev_err(&pdev->dev, "IR PNP IRQ not valid!\n");
495
goto failure;
496
}
497
498
fintek->cir_addr = pnp_port_start(pdev, 0);
499
fintek->cir_irq = pnp_irq(pdev, 0);
500
fintek->cir_port_len = pnp_port_len(pdev, 0);
501
502
fintek->cr_ip = CR_INDEX_PORT;
503
fintek->cr_dp = CR_DATA_PORT;
504
505
spin_lock_init(&fintek->fintek_lock);
506
507
ret = -EBUSY;
508
/* now claim resources */
509
if (!request_region(fintek->cir_addr,
510
fintek->cir_port_len, FINTEK_DRIVER_NAME))
511
goto failure;
512
513
if (request_irq(fintek->cir_irq, fintek_cir_isr, IRQF_SHARED,
514
FINTEK_DRIVER_NAME, (void *)fintek))
515
goto failure;
516
517
pnp_set_drvdata(pdev, fintek);
518
fintek->pdev = pdev;
519
520
ret = fintek_hw_detect(fintek);
521
if (ret)
522
goto failure;
523
524
/* Initialize CIR & CIR Wake Logical Devices */
525
fintek_config_mode_enable(fintek);
526
fintek_cir_ldev_init(fintek);
527
fintek_config_mode_disable(fintek);
528
529
/* Initialize CIR & CIR Wake Config Registers */
530
fintek_cir_regs_init(fintek);
531
532
/* Set up the rc device */
533
rdev->priv = fintek;
534
rdev->driver_type = RC_DRIVER_IR_RAW;
535
rdev->allowed_protos = RC_TYPE_ALL;
536
rdev->open = fintek_open;
537
rdev->close = fintek_close;
538
rdev->input_name = FINTEK_DESCRIPTION;
539
rdev->input_phys = "fintek/cir0";
540
rdev->input_id.bustype = BUS_HOST;
541
rdev->input_id.vendor = VENDOR_ID_FINTEK;
542
rdev->input_id.product = fintek->chip_major;
543
rdev->input_id.version = fintek->chip_minor;
544
rdev->dev.parent = &pdev->dev;
545
rdev->driver_name = FINTEK_DRIVER_NAME;
546
rdev->map_name = RC_MAP_RC6_MCE;
547
rdev->timeout = US_TO_NS(1000);
548
/* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */
549
rdev->rx_resolution = US_TO_NS(CIR_SAMPLE_PERIOD);
550
551
ret = rc_register_device(rdev);
552
if (ret)
553
goto failure;
554
555
device_init_wakeup(&pdev->dev, true);
556
fintek->rdev = rdev;
557
fit_pr(KERN_NOTICE, "driver has been successfully loaded\n");
558
if (debug)
559
cir_dump_regs(fintek);
560
561
return 0;
562
563
failure:
564
if (fintek->cir_irq)
565
free_irq(fintek->cir_irq, fintek);
566
if (fintek->cir_addr)
567
release_region(fintek->cir_addr, fintek->cir_port_len);
568
569
rc_free_device(rdev);
570
kfree(fintek);
571
572
return ret;
573
}
574
575
static void __devexit fintek_remove(struct pnp_dev *pdev)
576
{
577
struct fintek_dev *fintek = pnp_get_drvdata(pdev);
578
unsigned long flags;
579
580
spin_lock_irqsave(&fintek->fintek_lock, flags);
581
/* disable CIR */
582
fintek_disable_cir(fintek);
583
fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS);
584
/* enable CIR Wake (for IR power-on) */
585
fintek_enable_wake(fintek);
586
spin_unlock_irqrestore(&fintek->fintek_lock, flags);
587
588
/* free resources */
589
free_irq(fintek->cir_irq, fintek);
590
release_region(fintek->cir_addr, fintek->cir_port_len);
591
592
rc_unregister_device(fintek->rdev);
593
594
kfree(fintek);
595
}
596
597
static int fintek_suspend(struct pnp_dev *pdev, pm_message_t state)
598
{
599
struct fintek_dev *fintek = pnp_get_drvdata(pdev);
600
unsigned long flags;
601
602
fit_dbg("%s called", __func__);
603
604
spin_lock_irqsave(&fintek->fintek_lock, flags);
605
606
/* disable all CIR interrupts */
607
fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS);
608
609
spin_unlock_irqrestore(&fintek->fintek_lock, flags);
610
611
fintek_config_mode_enable(fintek);
612
613
/* disable cir logical dev */
614
fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR);
615
fintek_cr_write(fintek, LOGICAL_DEV_DISABLE, CIR_CR_DEV_EN);
616
617
fintek_config_mode_disable(fintek);
618
619
/* make sure wake is enabled */
620
fintek_enable_wake(fintek);
621
622
return 0;
623
}
624
625
static int fintek_resume(struct pnp_dev *pdev)
626
{
627
int ret = 0;
628
struct fintek_dev *fintek = pnp_get_drvdata(pdev);
629
630
fit_dbg("%s called", __func__);
631
632
/* open interrupt */
633
fintek_enable_cir_irq(fintek);
634
635
/* Enable CIR logical device */
636
fintek_config_mode_enable(fintek);
637
fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR);
638
fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN);
639
640
fintek_config_mode_disable(fintek);
641
642
fintek_cir_regs_init(fintek);
643
644
return ret;
645
}
646
647
static void fintek_shutdown(struct pnp_dev *pdev)
648
{
649
struct fintek_dev *fintek = pnp_get_drvdata(pdev);
650
fintek_enable_wake(fintek);
651
}
652
653
static const struct pnp_device_id fintek_ids[] = {
654
{ "FIT0002", 0 }, /* CIR */
655
{ "", 0 },
656
};
657
658
static struct pnp_driver fintek_driver = {
659
.name = FINTEK_DRIVER_NAME,
660
.id_table = fintek_ids,
661
.flags = PNP_DRIVER_RES_DO_NOT_CHANGE,
662
.probe = fintek_probe,
663
.remove = __devexit_p(fintek_remove),
664
.suspend = fintek_suspend,
665
.resume = fintek_resume,
666
.shutdown = fintek_shutdown,
667
};
668
669
int fintek_init(void)
670
{
671
return pnp_register_driver(&fintek_driver);
672
}
673
674
void fintek_exit(void)
675
{
676
pnp_unregister_driver(&fintek_driver);
677
}
678
679
module_param(debug, int, S_IRUGO | S_IWUSR);
680
MODULE_PARM_DESC(debug, "Enable debugging output");
681
682
MODULE_DEVICE_TABLE(pnp, fintek_ids);
683
MODULE_DESCRIPTION(FINTEK_DESCRIPTION " driver");
684
685
MODULE_AUTHOR("Jarod Wilson <[email protected]>");
686
MODULE_LICENSE("GPL");
687
688
module_init(fintek_init);
689
module_exit(fintek_exit);
690
691