diff options
author | Andy Walls <awalls@radix.net> | 2009-09-27 19:51:50 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-12-05 18:40:20 -0200 |
commit | f59ad611acccd4057b8e685c7fd5532ab1a17f66 (patch) | |
tree | 9c48a478ddc9a9f69c64c9e42f3db1f202970b78 /drivers/media/video/cx23885/cx23885-core.c | |
parent | 1a0b9d89c62ddf0aed12798686fe452e7e97de42 (diff) |
V4L/DVB (13098): cx23885: Add integrated IR subdevice interrupt and notification handling
Add integrated IR subdevice interrupt and notification handling. This is in
preparation of input keypress handling changes for the cx23885 module.
Signed-off-by: Andy Walls <awalls@radix.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/cx23885/cx23885-core.c')
-rw-r--r-- | drivers/media/video/cx23885/cx23885-core.c | 74 |
1 files changed, 60 insertions, 14 deletions
diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index 73be16b0d2a0..c879211a704d 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c @@ -33,6 +33,7 @@ #include "cx23885.h" #include "cimax2.h" #include "cx23888-ir.h" +#include "cx23885-ir.h" MODULE_DESCRIPTION("Driver for cx23885 based TV cards"); MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>"); @@ -1655,6 +1656,7 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) u32 ts1_status, ts1_mask; u32 ts2_status, ts2_mask; int vida_count = 0, ts1_count = 0, ts2_count = 0, handled = 0; + bool ir_handled = false; pci_status = cx_read(PCI_INT_STAT); pci_mask = cx_read(PCI_INT_MSK); @@ -1680,18 +1682,12 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) dprintk(7, "ts2_status: 0x%08x ts2_mask: 0x%08x count: 0x%x\n", ts2_status, ts2_mask, ts2_count); - if ((pci_status & PCI_MSK_RISC_RD) || - (pci_status & PCI_MSK_RISC_WR) || - (pci_status & PCI_MSK_AL_RD) || - (pci_status & PCI_MSK_AL_WR) || - (pci_status & PCI_MSK_APB_DMA) || - (pci_status & PCI_MSK_VID_C) || - (pci_status & PCI_MSK_VID_B) || - (pci_status & PCI_MSK_VID_A) || - (pci_status & PCI_MSK_AUD_INT) || - (pci_status & PCI_MSK_AUD_EXT) || - (pci_status & PCI_MSK_GPIO0) || - (pci_status & PCI_MSK_GPIO1)) { + if (pci_status & (PCI_MSK_RISC_RD | PCI_MSK_RISC_WR | + PCI_MSK_AL_RD | PCI_MSK_AL_WR | PCI_MSK_APB_DMA | + PCI_MSK_VID_C | PCI_MSK_VID_B | PCI_MSK_VID_A | + PCI_MSK_AUD_INT | PCI_MSK_AUD_EXT | + PCI_MSK_GPIO0 | PCI_MSK_GPIO1 | + PCI_MSK_IR)) { if (pci_status & PCI_MSK_RISC_RD) dprintk(7, " (PCI_MSK_RISC_RD 0x%08x)\n", @@ -1740,6 +1736,10 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) if (pci_status & PCI_MSK_GPIO1) dprintk(7, " (PCI_MSK_GPIO1 0x%08x)\n", PCI_MSK_GPIO1); + + if (pci_status & PCI_MSK_IR) + dprintk(7, " (PCI_MSK_IR 0x%08x)\n", + PCI_MSK_IR); } if (cx23885_boards[dev->board].cimax > 0 && @@ -1770,12 +1770,48 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) if (vida_status) handled += cx23885_video_irq(dev, vida_status); + if (pci_status & PCI_MSK_IR) { + v4l2_subdev_call(dev->sd_ir, ir, interrupt_service_routine, + pci_status, &ir_handled); + if (ir_handled) + handled++; + } + if (handled) cx_write(PCI_INT_STAT, pci_status); out: return IRQ_RETVAL(handled); } +static void cx23885_v4l2_dev_notify(struct v4l2_subdev *sd, + unsigned int notification, void *arg) +{ + struct cx23885_dev *dev; + + if (sd == NULL) + return; + + dev = to_cx23885(sd->v4l2_dev); + + switch (notification) { + case V4L2_SUBDEV_IR_RX_NOTIFY: /* Called in an IRQ context */ + if (sd == dev->sd_ir) + cx23885_ir_rx_v4l2_dev_notify(sd, *(u32 *)arg); + break; + case V4L2_SUBDEV_IR_TX_NOTIFY: /* Called in an IRQ context */ + if (sd == dev->sd_ir) + cx23885_ir_tx_v4l2_dev_notify(sd, *(u32 *)arg); + break; + } +} + +static void cx23885_v4l2_dev_notify_init(struct cx23885_dev *dev) +{ + INIT_WORK(&dev->ir_rx_work, cx23885_ir_rx_work_handler); + INIT_WORK(&dev->ir_tx_work, cx23885_ir_tx_work_handler); + dev->v4l2_dev.notify = cx23885_v4l2_dev_notify; +} + static inline int encoder_on_portb(struct cx23885_dev *dev) { return cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER; @@ -1872,6 +1908,9 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev, if (err < 0) goto fail_free; + /* Prepare to handle notifications from subdevices */ + cx23885_v4l2_dev_notify_init(dev); + /* pci init */ dev->pci = pci_dev; if (pci_enable_device(pci_dev)) { @@ -1914,6 +1953,13 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev, break; } + /* + * The CX2388[58] IR controller can start firing interrupts when + * enabled, so these have to take place after the cx23885_irq() handler + * is hooked up by the call to request_irq() above. + */ + cx23885_ir_pci_int_enable(dev); + return 0; fail_irq: @@ -1930,9 +1976,9 @@ static void __devexit cx23885_finidev(struct pci_dev *pci_dev) struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); struct cx23885_dev *dev = to_cx23885(v4l2_dev); - cx23885_shutdown(dev); + cx23885_ir_fini(dev); - cx23888_ir_remove(dev); + cx23885_shutdown(dev); pci_disable_device(pci_dev); |