Version:  2.0.40 2.2.26 2.4.37 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1 4.2 4.3 4.4 4.5

Linux/drivers/media/rc/fintek-cir.c

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

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us