aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx23885
diff options
context:
space:
mode:
authorAndy Walls <awalls@radix.net>2009-09-27 18:51:50 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-12-05 15:40:20 -0500
commitf59ad611acccd4057b8e685c7fd5532ab1a17f66 (patch)
tree9c48a478ddc9a9f69c64c9e42f3db1f202970b78 /drivers/media/video/cx23885
parent1a0b9d89c62ddf0aed12798686fe452e7e97de42 (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')
-rw-r--r--drivers/media/video/cx23885/Makefile2
-rw-r--r--drivers/media/video/cx23885/cx23885-cards.c23
-rw-r--r--drivers/media/video/cx23885/cx23885-core.c74
-rw-r--r--drivers/media/video/cx23885/cx23885-ir.c97
-rw-r--r--drivers/media/video/cx23885/cx23885-ir.h31
-rw-r--r--drivers/media/video/cx23885/cx23885-reg.h5
-rw-r--r--drivers/media/video/cx23885/cx23885.h10
7 files changed, 224 insertions, 18 deletions
diff --git a/drivers/media/video/cx23885/Makefile b/drivers/media/video/cx23885/Makefile
index 3832a1cb768d..330cff3f77ac 100644
--- a/drivers/media/video/cx23885/Makefile
+++ b/drivers/media/video/cx23885/Makefile
@@ -1,6 +1,6 @@
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 cx23888-ir.o \ 3 cx23885-ioctl.o cx23885-ir.o cx23888-ir.o \
4 netup-init.o cimax2.o netup-eeprom.o 4 netup-init.o cimax2.o netup-eeprom.o
5 5
6obj-$(CONFIG_VIDEO_CX23885) += cx23885.o 6obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c
index 7c5d13ac538e..c0e2409f3cbd 100644
--- a/drivers/media/video/cx23885/cx23885-cards.c
+++ b/drivers/media/video/cx23885/cx23885-cards.c
@@ -821,6 +821,7 @@ int cx23885_ir_init(struct cx23885_dev *dev)
821 if (ret) 821 if (ret)
822 break; 822 break;
823 dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_888_IR); 823 dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_888_IR);
824 dev->pci_irqmask |= PCI_MSK_IR;
824 break; 825 break;
825 case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: 826 case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
826 request_module("ir-kbd-i2c"); 827 request_module("ir-kbd-i2c");
@@ -830,6 +831,28 @@ int cx23885_ir_init(struct cx23885_dev *dev)
830 return ret; 831 return ret;
831} 832}
832 833
834void cx23885_ir_fini(struct cx23885_dev *dev)
835{
836 switch (dev->board) {
837 case CX23885_BOARD_HAUPPAUGE_HVR1850:
838 dev->pci_irqmask &= ~PCI_MSK_IR;
839 cx_clear(PCI_INT_MSK, PCI_MSK_IR);
840 cx23888_ir_remove(dev);
841 dev->sd_ir = NULL;
842 break;
843 }
844}
845
846void cx23885_ir_pci_int_enable(struct cx23885_dev *dev)
847{
848 switch (dev->board) {
849 case CX23885_BOARD_HAUPPAUGE_HVR1850:
850 if (dev->sd_ir && (dev->pci_irqmask & PCI_MSK_IR))
851 cx_set(PCI_INT_MSK, PCI_MSK_IR);
852 break;
853 }
854}
855
833void cx23885_card_setup(struct cx23885_dev *dev) 856void cx23885_card_setup(struct cx23885_dev *dev)
834{ 857{
835 struct cx23885_tsport *ts1 = &dev->ts1; 858 struct cx23885_tsport *ts1 = &dev->ts1;
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 @@
33#include "cx23885.h" 33#include "cx23885.h"
34#include "cimax2.h" 34#include "cimax2.h"
35#include "cx23888-ir.h" 35#include "cx23888-ir.h"
36#include "cx23885-ir.h"
36 37
37MODULE_DESCRIPTION("Driver for cx23885 based TV cards"); 38MODULE_DESCRIPTION("Driver for cx23885 based TV cards");
38MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>"); 39MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
@@ -1655,6 +1656,7 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
1655 u32 ts1_status, ts1_mask; 1656 u32 ts1_status, ts1_mask;
1656 u32 ts2_status, ts2_mask; 1657 u32 ts2_status, ts2_mask;
1657 int vida_count = 0, ts1_count = 0, ts2_count = 0, handled = 0; 1658 int vida_count = 0, ts1_count = 0, ts2_count = 0, handled = 0;
1659 bool ir_handled = false;
1658 1660
1659 pci_status = cx_read(PCI_INT_STAT); 1661 pci_status = cx_read(PCI_INT_STAT);
1660 pci_mask = cx_read(PCI_INT_MSK); 1662 pci_mask = cx_read(PCI_INT_MSK);
@@ -1680,18 +1682,12 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
1680 dprintk(7, "ts2_status: 0x%08x ts2_mask: 0x%08x count: 0x%x\n", 1682 dprintk(7, "ts2_status: 0x%08x ts2_mask: 0x%08x count: 0x%x\n",
1681 ts2_status, ts2_mask, ts2_count); 1683 ts2_status, ts2_mask, ts2_count);
1682 1684
1683 if ((pci_status & PCI_MSK_RISC_RD) || 1685 if (pci_status & (PCI_MSK_RISC_RD | PCI_MSK_RISC_WR |
1684 (pci_status & PCI_MSK_RISC_WR) || 1686 PCI_MSK_AL_RD | PCI_MSK_AL_WR | PCI_MSK_APB_DMA |
1685 (pci_status & PCI_MSK_AL_RD) || 1687 PCI_MSK_VID_C | PCI_MSK_VID_B | PCI_MSK_VID_A |
1686 (pci_status & PCI_MSK_AL_WR) || 1688 PCI_MSK_AUD_INT | PCI_MSK_AUD_EXT |
1687 (pci_status & PCI_MSK_APB_DMA) || 1689 PCI_MSK_GPIO0 | PCI_MSK_GPIO1 |
1688 (pci_status & PCI_MSK_VID_C) || 1690 PCI_MSK_IR)) {
1689 (pci_status & PCI_MSK_VID_B) ||
1690 (pci_status & PCI_MSK_VID_A) ||
1691 (pci_status & PCI_MSK_AUD_INT) ||
1692 (pci_status & PCI_MSK_AUD_EXT) ||
1693 (pci_status & PCI_MSK_GPIO0) ||
1694 (pci_status & PCI_MSK_GPIO1)) {
1695 1691
1696 if (pci_status & PCI_MSK_RISC_RD) 1692 if (pci_status & PCI_MSK_RISC_RD)
1697 dprintk(7, " (PCI_MSK_RISC_RD 0x%08x)\n", 1693 dprintk(7, " (PCI_MSK_RISC_RD 0x%08x)\n",
@@ -1740,6 +1736,10 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
1740 if (pci_status & PCI_MSK_GPIO1) 1736 if (pci_status & PCI_MSK_GPIO1)
1741 dprintk(7, " (PCI_MSK_GPIO1 0x%08x)\n", 1737 dprintk(7, " (PCI_MSK_GPIO1 0x%08x)\n",
1742 PCI_MSK_GPIO1); 1738 PCI_MSK_GPIO1);
1739
1740 if (pci_status & PCI_MSK_IR)
1741 dprintk(7, " (PCI_MSK_IR 0x%08x)\n",
1742 PCI_MSK_IR);
1743 } 1743 }
1744 1744
1745 if (cx23885_boards[dev->board].cimax > 0 && 1745 if (cx23885_boards[dev->board].cimax > 0 &&
@@ -1770,12 +1770,48 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
1770 if (vida_status) 1770 if (vida_status)
1771 handled += cx23885_video_irq(dev, vida_status); 1771 handled += cx23885_video_irq(dev, vida_status);
1772 1772
1773 if (pci_status & PCI_MSK_IR) {
1774 v4l2_subdev_call(dev->sd_ir, ir, interrupt_service_routine,
1775 pci_status, &ir_handled);
1776 if (ir_handled)
1777 handled++;
1778 }
1779
1773 if (handled) 1780 if (handled)
1774 cx_write(PCI_INT_STAT, pci_status); 1781 cx_write(PCI_INT_STAT, pci_status);
1775out: 1782out:
1776 return IRQ_RETVAL(handled); 1783 return IRQ_RETVAL(handled);
1777} 1784}
1778 1785
1786static void cx23885_v4l2_dev_notify(struct v4l2_subdev *sd,
1787 unsigned int notification, void *arg)
1788{
1789 struct cx23885_dev *dev;
1790
1791 if (sd == NULL)
1792 return;
1793
1794 dev = to_cx23885(sd->v4l2_dev);
1795
1796 switch (notification) {
1797 case V4L2_SUBDEV_IR_RX_NOTIFY: /* Called in an IRQ context */
1798 if (sd == dev->sd_ir)
1799 cx23885_ir_rx_v4l2_dev_notify(sd, *(u32 *)arg);
1800 break;
1801 case V4L2_SUBDEV_IR_TX_NOTIFY: /* Called in an IRQ context */
1802 if (sd == dev->sd_ir)
1803 cx23885_ir_tx_v4l2_dev_notify(sd, *(u32 *)arg);
1804 break;
1805 }
1806}
1807
1808static void cx23885_v4l2_dev_notify_init(struct cx23885_dev *dev)
1809{
1810 INIT_WORK(&dev->ir_rx_work, cx23885_ir_rx_work_handler);
1811 INIT_WORK(&dev->ir_tx_work, cx23885_ir_tx_work_handler);
1812 dev->v4l2_dev.notify = cx23885_v4l2_dev_notify;
1813}
1814
1779static inline int encoder_on_portb(struct cx23885_dev *dev) 1815static inline int encoder_on_portb(struct cx23885_dev *dev)
1780{ 1816{
1781 return cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER; 1817 return cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER;
@@ -1872,6 +1908,9 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev,
1872 if (err < 0) 1908 if (err < 0)
1873 goto fail_free; 1909 goto fail_free;
1874 1910
1911 /* Prepare to handle notifications from subdevices */
1912 cx23885_v4l2_dev_notify_init(dev);
1913
1875 /* pci init */ 1914 /* pci init */
1876 dev->pci = pci_dev; 1915 dev->pci = pci_dev;
1877 if (pci_enable_device(pci_dev)) { 1916 if (pci_enable_device(pci_dev)) {
@@ -1914,6 +1953,13 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev,
1914 break; 1953 break;
1915 } 1954 }
1916 1955
1956 /*
1957 * The CX2388[58] IR controller can start firing interrupts when
1958 * enabled, so these have to take place after the cx23885_irq() handler
1959 * is hooked up by the call to request_irq() above.
1960 */
1961 cx23885_ir_pci_int_enable(dev);
1962
1917 return 0; 1963 return 0;
1918 1964
1919fail_irq: 1965fail_irq:
@@ -1930,9 +1976,9 @@ static void __devexit cx23885_finidev(struct pci_dev *pci_dev)
1930 struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); 1976 struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
1931 struct cx23885_dev *dev = to_cx23885(v4l2_dev); 1977 struct cx23885_dev *dev = to_cx23885(v4l2_dev);
1932 1978
1933 cx23885_shutdown(dev); 1979 cx23885_ir_fini(dev);
1934 1980
1935 cx23888_ir_remove(dev); 1981 cx23885_shutdown(dev);
1936 1982
1937 pci_disable_device(pci_dev); 1983 pci_disable_device(pci_dev);
1938 1984
diff --git a/drivers/media/video/cx23885/cx23885-ir.c b/drivers/media/video/cx23885/cx23885-ir.c
new file mode 100644
index 000000000000..e84f90c75bf1
--- /dev/null
+++ b/drivers/media/video/cx23885/cx23885-ir.c
@@ -0,0 +1,97 @@
1/*
2 * Driver for the Conexant CX23885/7/8 PCIe bridge
3 *
4 * Infrared device support routines - non-input, non-vl42_subdev routines
5 *
6 * Copyright (C) 2009 Andy Walls <awalls@radix.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 <media/v4l2-device.h>
25
26#include "cx23885.h"
27
28#define CX23885_IR_RX_FIFO_SERVICE_REQ 0
29#define CX23885_IR_RX_END_OF_RX_DETECTED 1
30#define CX23885_IR_RX_HW_FIFO_OVERRUN 2
31#define CX23885_IR_RX_SW_FIFO_OVERRUN 3
32
33#define CX23885_IR_TX_FIFO_SERVICE_REQ 0
34
35
36void cx23885_ir_rx_work_handler(struct work_struct *work)
37{
38 struct cx23885_dev *dev =
39 container_of(work, struct cx23885_dev, ir_rx_work);
40 u32 events = 0;
41 unsigned long *notifications = &dev->ir_rx_notifications;
42
43 if (test_and_clear_bit(CX23885_IR_RX_SW_FIFO_OVERRUN, notifications))
44 events |= V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN;
45 if (test_and_clear_bit(CX23885_IR_RX_HW_FIFO_OVERRUN, notifications))
46 events |= V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN;
47 if (test_and_clear_bit(CX23885_IR_RX_END_OF_RX_DETECTED, notifications))
48 events |= V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED;
49 if (test_and_clear_bit(CX23885_IR_RX_FIFO_SERVICE_REQ, notifications))
50 events |= V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ;
51
52 if (events == 0)
53 return;
54}
55
56void cx23885_ir_tx_work_handler(struct work_struct *work)
57{
58 struct cx23885_dev *dev =
59 container_of(work, struct cx23885_dev, ir_tx_work);
60 u32 events = 0;
61 unsigned long *notifications = &dev->ir_tx_notifications;
62
63 if (test_and_clear_bit(CX23885_IR_TX_FIFO_SERVICE_REQ, notifications))
64 events |= V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ;
65
66 if (events == 0)
67 return;
68
69}
70
71/* Called in an IRQ context */
72void cx23885_ir_rx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events)
73{
74 struct cx23885_dev *dev = to_cx23885(sd->v4l2_dev);
75 unsigned long *notifications = &dev->ir_rx_notifications;
76
77 if (events & V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ)
78 set_bit(CX23885_IR_RX_FIFO_SERVICE_REQ, notifications);
79 if (events & V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED)
80 set_bit(CX23885_IR_RX_END_OF_RX_DETECTED, notifications);
81 if (events & V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN)
82 set_bit(CX23885_IR_RX_HW_FIFO_OVERRUN, notifications);
83 if (events & V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN)
84 set_bit(CX23885_IR_RX_SW_FIFO_OVERRUN, notifications);
85 schedule_work(&dev->ir_rx_work);
86}
87
88/* Called in an IRQ context */
89void cx23885_ir_tx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events)
90{
91 struct cx23885_dev *dev = to_cx23885(sd->v4l2_dev);
92 unsigned long *notifications = &dev->ir_tx_notifications;
93
94 if (events & V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ)
95 set_bit(CX23885_IR_TX_FIFO_SERVICE_REQ, notifications);
96 schedule_work(&dev->ir_tx_work);
97}
diff --git a/drivers/media/video/cx23885/cx23885-ir.h b/drivers/media/video/cx23885/cx23885-ir.h
new file mode 100644
index 000000000000..9b8a6d5d1ef6
--- /dev/null
+++ b/drivers/media/video/cx23885/cx23885-ir.h
@@ -0,0 +1,31 @@
1/*
2 * Driver for the Conexant CX23885/7/8 PCIe bridge
3 *
4 * Infrared device support routines - non-input, non-vl42_subdev routines
5 *
6 * Copyright (C) 2009 Andy Walls <awalls@radix.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_IR_H_
25#define _CX23885_IR_H_
26void cx23885_ir_rx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events);
27void cx23885_ir_tx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events);
28
29void cx23885_ir_rx_work_handler(struct work_struct *work);
30void cx23885_ir_tx_work_handler(struct work_struct *work);
31#endif
diff --git a/drivers/media/video/cx23885/cx23885-reg.h b/drivers/media/video/cx23885/cx23885-reg.h
index eafbe5226bae..c0bc9a068954 100644
--- a/drivers/media/video/cx23885/cx23885-reg.h
+++ b/drivers/media/video/cx23885/cx23885-reg.h
@@ -212,8 +212,9 @@ Channel manager Data Structure entry = 20 DWORD
212 212
213#define DEV_CNTRL2 0x00040000 213#define DEV_CNTRL2 0x00040000
214 214
215#define PCI_MSK_GPIO1 (1 << 24) 215#define PCI_MSK_IR (1 << 28)
216#define PCI_MSK_GPIO0 (1 << 23) 216#define PCI_MSK_GPIO1 (1 << 24)
217#define PCI_MSK_GPIO0 (1 << 23)
217#define PCI_MSK_APB_DMA (1 << 12) 218#define PCI_MSK_APB_DMA (1 << 12)
218#define PCI_MSK_AL_WR (1 << 11) 219#define PCI_MSK_AL_WR (1 << 11)
219#define PCI_MSK_AL_RD (1 << 10) 220#define PCI_MSK_AL_RD (1 << 10)
diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h
index f7ed146566d9..ce82698db5f7 100644
--- a/drivers/media/video/cx23885/cx23885.h
+++ b/drivers/media/video/cx23885/cx23885.h
@@ -355,7 +355,13 @@ struct cx23885_dev {
355 unsigned char radio_addr; 355 unsigned char radio_addr;
356 unsigned int has_radio; 356 unsigned int has_radio;
357 struct v4l2_subdev *sd_cx25840; 357 struct v4l2_subdev *sd_cx25840;
358 struct v4l2_subdev *sd_ir; 358
359 /* Infrared */
360 struct v4l2_subdev *sd_ir;
361 struct work_struct ir_rx_work;
362 unsigned long ir_rx_notifications;
363 struct work_struct ir_tx_work;
364 unsigned long ir_tx_notifications;
359 365
360 /* V4l */ 366 /* V4l */
361 u32 freq; 367 u32 freq;
@@ -479,6 +485,8 @@ extern int cx23885_tuner_callback(void *priv, int component,
479 int command, int arg); 485 int command, int arg);
480extern void cx23885_card_list(struct cx23885_dev *dev); 486extern void cx23885_card_list(struct cx23885_dev *dev);
481extern int cx23885_ir_init(struct cx23885_dev *dev); 487extern int cx23885_ir_init(struct cx23885_dev *dev);
488extern void cx23885_ir_pci_int_enable(struct cx23885_dev *dev);
489extern void cx23885_ir_fini(struct cx23885_dev *dev);
482extern void cx23885_gpio_setup(struct cx23885_dev *dev); 490extern void cx23885_gpio_setup(struct cx23885_dev *dev);
483extern void cx23885_card_setup(struct cx23885_dev *dev); 491extern void cx23885_card_setup(struct cx23885_dev *dev);
484extern void cx23885_card_setup_pre_i2c(struct cx23885_dev *dev); 492extern void cx23885_card_setup_pre_i2c(struct cx23885_dev *dev);