Version:  2.0.40 2.2.26 2.4.37 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 4.6 4.7 4.8 4.9 4.10

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

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