aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video
diff options
context:
space:
mode:
authorAndy Walls <awalls@md.metrocast.net>2010-07-19 00:35:46 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-08-08 22:42:56 -0400
commite5514f104d875b3d28cbcd5d4f2b96ab2fca1e29 (patch)
tree8869a2ac0445351e9da7a20304d44d3f5994b3fc /drivers/media/video
parentdbe83a3b921328e12b2abe894fc692afba293d7f (diff)
V4L/DVB: cx23885: Move AV Core irq handling to a work handler
Interrupts from the AV Core are best handled by a workqueue handler since many I2C transactions are required to service the AV Core interrupt. The AV_CORE PCI interrupt is disabled by the IRQ handler and reenabled when the work handler is finished. Signed-off-by: Andy Walls <awalls@md.metrocast.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video')
-rw-r--r--drivers/media/video/cx23885/Makefile5
-rw-r--r--drivers/media/video/cx23885/cx23885-av.c35
-rw-r--r--drivers/media/video/cx23885/cx23885-av.h27
-rw-r--r--drivers/media/video/cx23885/cx23885-core.c20
-rw-r--r--drivers/media/video/cx23885/cx23885-ir.c24
-rw-r--r--drivers/media/video/cx23885/cx23885.h1
6 files changed, 97 insertions, 15 deletions
diff --git a/drivers/media/video/cx23885/Makefile b/drivers/media/video/cx23885/Makefile
index 5787ae243631..e2ee95f660d8 100644
--- a/drivers/media/video/cx23885/Makefile
+++ b/drivers/media/video/cx23885/Makefile
@@ -1,7 +1,8 @@
1cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o \ 1cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o \
2 cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o \ 2 cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o \
3 cx23885-ioctl.o cx23885-ir.o cx23885-input.o cx23888-ir.o \ 3 cx23885-ioctl.o cx23885-ir.o cx23885-av.o cx23885-input.o \
4 netup-init.o cimax2.o netup-eeprom.o cx23885-f300.o 4 cx23888-ir.o netup-init.o cimax2.o netup-eeprom.o \
5 cx23885-f300.o
5 6
6obj-$(CONFIG_VIDEO_CX23885) += cx23885.o 7obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
7 8
diff --git a/drivers/media/video/cx23885/cx23885-av.c b/drivers/media/video/cx23885/cx23885-av.c
new file mode 100644
index 000000000000..134ebddd860f
--- /dev/null
+++ b/drivers/media/video/cx23885/cx23885-av.c
@@ -0,0 +1,35 @@
1/*
2 * Driver for the Conexant CX23885/7/8 PCIe bridge
3 *
4 * AV device support routines - non-input, non-vl42_subdev routines
5 *
6 * Copyright (C) 2010 Andy Walls <awalls@md.metrocast.net>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 * 02110-1301, USA.
22 */
23
24#include "cx23885.h"
25
26void cx23885_av_work_handler(struct work_struct *work)
27{
28 struct cx23885_dev *dev =
29 container_of(work, struct cx23885_dev, cx25840_work);
30 bool handled;
31
32 v4l2_subdev_call(dev->sd_cx25840, core, interrupt_service_routine,
33 PCI_MSK_AV_CORE, &handled);
34 cx23885_irq_enable(dev, PCI_MSK_AV_CORE);
35}
diff --git a/drivers/media/video/cx23885/cx23885-av.h b/drivers/media/video/cx23885/cx23885-av.h
new file mode 100644
index 000000000000..d2915c3e53a2
--- /dev/null
+++ b/drivers/media/video/cx23885/cx23885-av.h
@@ -0,0 +1,27 @@
1/*
2 * Driver for the Conexant CX23885/7/8 PCIe bridge
3 *
4 * AV device support routines - non-input, non-vl42_subdev routines
5 *
6 * Copyright (C) 2010 Andy Walls <awalls@md.metrocast.net>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 * 02110-1301, USA.
22 */
23
24#ifndef _CX23885_AV_H_
25#define _CX23885_AV_H_
26void cx23885_av_work_handler(struct work_struct *work);
27#endif
diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c
index 0765abf4e42e..f6b62e7398af 100644
--- a/drivers/media/video/cx23885/cx23885-core.c
+++ b/drivers/media/video/cx23885/cx23885-core.c
@@ -34,6 +34,7 @@
34#include "cimax2.h" 34#include "cimax2.h"
35#include "cx23888-ir.h" 35#include "cx23888-ir.h"
36#include "cx23885-ir.h" 36#include "cx23885-ir.h"
37#include "cx23885-av.h"
37#include "cx23885-input.h" 38#include "cx23885-input.h"
38 39
39MODULE_DESCRIPTION("Driver for cx23885 based TV cards"); 40MODULE_DESCRIPTION("Driver for cx23885 based TV cards");
@@ -1856,13 +1857,13 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
1856 handled++; 1857 handled++;
1857 } 1858 }
1858 1859
1859 if (pci_status & PCI_MSK_AV_CORE) { 1860 if ((pci_status & pci_mask) & PCI_MSK_AV_CORE) {
1860 subdev_handled = false; 1861 cx23885_irq_disable(dev, PCI_MSK_AV_CORE);
1861 v4l2_subdev_call(dev->sd_cx25840, 1862 if (!schedule_work(&dev->cx25840_work))
1862 core, interrupt_service_routine, 1863 printk(KERN_ERR "%s: failed to set up deferred work for"
1863 pci_status, &subdev_handled); 1864 " AV Core/IR interrupt. Interrupt is disabled"
1864 if (subdev_handled) 1865 " and won't be re-enabled\n", dev->name);
1865 handled++; 1866 handled++;
1866 } 1867 }
1867 1868
1868 if (handled) 1869 if (handled)
@@ -1882,11 +1883,11 @@ static void cx23885_v4l2_dev_notify(struct v4l2_subdev *sd,
1882 dev = to_cx23885(sd->v4l2_dev); 1883 dev = to_cx23885(sd->v4l2_dev);
1883 1884
1884 switch (notification) { 1885 switch (notification) {
1885 case V4L2_SUBDEV_IR_RX_NOTIFY: /* Called in an IRQ context */ 1886 case V4L2_SUBDEV_IR_RX_NOTIFY: /* Possibly called in an IRQ context */
1886 if (sd == dev->sd_ir) 1887 if (sd == dev->sd_ir)
1887 cx23885_ir_rx_v4l2_dev_notify(sd, *(u32 *)arg); 1888 cx23885_ir_rx_v4l2_dev_notify(sd, *(u32 *)arg);
1888 break; 1889 break;
1889 case V4L2_SUBDEV_IR_TX_NOTIFY: /* Called in an IRQ context */ 1890 case V4L2_SUBDEV_IR_TX_NOTIFY: /* Possibly called in an IRQ context */
1890 if (sd == dev->sd_ir) 1891 if (sd == dev->sd_ir)
1891 cx23885_ir_tx_v4l2_dev_notify(sd, *(u32 *)arg); 1892 cx23885_ir_tx_v4l2_dev_notify(sd, *(u32 *)arg);
1892 break; 1893 break;
@@ -1895,6 +1896,7 @@ static void cx23885_v4l2_dev_notify(struct v4l2_subdev *sd,
1895 1896
1896static void cx23885_v4l2_dev_notify_init(struct cx23885_dev *dev) 1897static void cx23885_v4l2_dev_notify_init(struct cx23885_dev *dev)
1897{ 1898{
1899 INIT_WORK(&dev->cx25840_work, cx23885_av_work_handler);
1898 INIT_WORK(&dev->ir_rx_work, cx23885_ir_rx_work_handler); 1900 INIT_WORK(&dev->ir_rx_work, cx23885_ir_rx_work_handler);
1899 INIT_WORK(&dev->ir_tx_work, cx23885_ir_tx_work_handler); 1901 INIT_WORK(&dev->ir_tx_work, cx23885_ir_tx_work_handler);
1900 dev->v4l2_dev.notify = cx23885_v4l2_dev_notify; 1902 dev->v4l2_dev.notify = cx23885_v4l2_dev_notify;
diff --git a/drivers/media/video/cx23885/cx23885-ir.c b/drivers/media/video/cx23885/cx23885-ir.c
index 6ceabd4fba07..7125247dd255 100644
--- a/drivers/media/video/cx23885/cx23885-ir.c
+++ b/drivers/media/video/cx23885/cx23885-ir.c
@@ -72,7 +72,7 @@ void cx23885_ir_tx_work_handler(struct work_struct *work)
72 72
73} 73}
74 74
75/* Called in an IRQ context */ 75/* Possibly called in an IRQ context */
76void cx23885_ir_rx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events) 76void cx23885_ir_rx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events)
77{ 77{
78 struct cx23885_dev *dev = to_cx23885(sd->v4l2_dev); 78 struct cx23885_dev *dev = to_cx23885(sd->v4l2_dev);
@@ -86,10 +86,18 @@ void cx23885_ir_rx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events)
86 set_bit(CX23885_IR_RX_HW_FIFO_OVERRUN, notifications); 86 set_bit(CX23885_IR_RX_HW_FIFO_OVERRUN, notifications);
87 if (events & V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN) 87 if (events & V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN)
88 set_bit(CX23885_IR_RX_SW_FIFO_OVERRUN, notifications); 88 set_bit(CX23885_IR_RX_SW_FIFO_OVERRUN, notifications);
89 schedule_work(&dev->ir_rx_work); 89
90 /*
91 * For the integrated AV core, we are already in a workqueue context.
92 * For the CX23888 integrated IR, we are in an interrupt context.
93 */
94 if (sd == dev->sd_cx25840)
95 cx23885_ir_rx_work_handler(&dev->ir_rx_work);
96 else
97 schedule_work(&dev->ir_rx_work);
90} 98}
91 99
92/* Called in an IRQ context */ 100/* Possibly called in an IRQ context */
93void cx23885_ir_tx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events) 101void cx23885_ir_tx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events)
94{ 102{
95 struct cx23885_dev *dev = to_cx23885(sd->v4l2_dev); 103 struct cx23885_dev *dev = to_cx23885(sd->v4l2_dev);
@@ -97,5 +105,13 @@ void cx23885_ir_tx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events)
97 105
98 if (events & V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ) 106 if (events & V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ)
99 set_bit(CX23885_IR_TX_FIFO_SERVICE_REQ, notifications); 107 set_bit(CX23885_IR_TX_FIFO_SERVICE_REQ, notifications);
100 schedule_work(&dev->ir_tx_work); 108
109 /*
110 * For the integrated AV core, we are already in a workqueue context.
111 * For the CX23888 integrated IR, we are in an interrupt context.
112 */
113 if (sd == dev->sd_cx25840)
114 cx23885_ir_tx_work_handler(&dev->ir_tx_work);
115 else
116 schedule_work(&dev->ir_tx_work);
101} 117}
diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h
index 5bf6ed09c970..ed94b17dd8a5 100644
--- a/drivers/media/video/cx23885/cx23885.h
+++ b/drivers/media/video/cx23885/cx23885.h
@@ -366,6 +366,7 @@ struct cx23885_dev {
366 unsigned char radio_addr; 366 unsigned char radio_addr;
367 unsigned int has_radio; 367 unsigned int has_radio;
368 struct v4l2_subdev *sd_cx25840; 368 struct v4l2_subdev *sd_cx25840;
369 struct work_struct cx25840_work;
369 370
370 /* Infrared */ 371 /* Infrared */
371 struct v4l2_subdev *sd_ir; 372 struct v4l2_subdev *sd_ir;