aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorAndy Walls <awalls@md.metrocast.net>2010-07-18 23:41:41 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-08-08 22:42:55 -0400
commit98d109f90fc02ce8baf1c2471ffcf8d66fb0d8e6 (patch)
treedf1a3191953696bcccc618a25f749ee8071565a9 /drivers/media
parentd6b1850d3c49e66f17bbb67f964a48b11528f56b (diff)
V4L/DVB: cx23885: Add preliminary IR Rx support for the HVR-1250 and TeVii S470
Add initial IR Rx support using the intergrated IR controller in the A/V core of the CX23885 bridge chip. This initial support is flawed in that I2C transactions should not be performed in a hard irq context. That will be fixed in a follow on patch. The TeVii S470 support is reported to generate perptual interrupts that renders a user' system nearly unusable. The TeVii S470 IR will be disabled by default in a follow on patch. Signed-off-by: Andy Walls <awalls@md.metrocast.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/cx23885/cx23885-cards.c52
-rw-r--r--drivers/media/video/cx23885/cx23885-core.c22
-rw-r--r--drivers/media/video/cx23885/cx23885-input.c46
-rw-r--r--drivers/media/video/cx23885/cx23885-reg.h1
4 files changed, 111 insertions, 10 deletions
diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c
index b083e5dfb715..294a7530caf7 100644
--- a/drivers/media/video/cx23885/cx23885-cards.c
+++ b/drivers/media/video/cx23885/cx23885-cards.c
@@ -962,7 +962,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
962 962
963int cx23885_ir_init(struct cx23885_dev *dev) 963int cx23885_ir_init(struct cx23885_dev *dev)
964{ 964{
965 static struct v4l2_subdev_io_pin_config ir_pin_cfg[] = { 965 static struct v4l2_subdev_io_pin_config ir_rxtx_pin_cfg[] = {
966 { 966 {
967 .flags = V4L2_SUBDEV_IO_PIN_INPUT, 967 .flags = V4L2_SUBDEV_IO_PIN_INPUT,
968 .pin = CX23885_PIN_IR_RX_GPIO19, 968 .pin = CX23885_PIN_IR_RX_GPIO19,
@@ -977,12 +977,22 @@ int cx23885_ir_init(struct cx23885_dev *dev)
977 .strength = CX25840_PIN_DRIVE_MEDIUM, 977 .strength = CX25840_PIN_DRIVE_MEDIUM,
978 } 978 }
979 }; 979 };
980 const size_t ir_pin_cfg_count = ARRAY_SIZE(ir_pin_cfg); 980 const size_t ir_rxtx_pin_cfg_count = ARRAY_SIZE(ir_rxtx_pin_cfg);
981
982 static struct v4l2_subdev_io_pin_config ir_rx_pin_cfg[] = {
983 {
984 .flags = V4L2_SUBDEV_IO_PIN_INPUT,
985 .pin = CX23885_PIN_IR_RX_GPIO19,
986 .function = CX23885_PAD_IR_RX,
987 .value = 0,
988 .strength = CX25840_PIN_DRIVE_MEDIUM,
989 }
990 };
991 const size_t ir_rx_pin_cfg_count = ARRAY_SIZE(ir_rx_pin_cfg);
981 992
982 struct v4l2_subdev_ir_parameters params; 993 struct v4l2_subdev_ir_parameters params;
983 int ret = 0; 994 int ret = 0;
984 switch (dev->board) { 995 switch (dev->board) {
985 case CX23885_BOARD_HAUPPAUGE_HVR1250:
986 case CX23885_BOARD_HAUPPAUGE_HVR1500: 996 case CX23885_BOARD_HAUPPAUGE_HVR1500:
987 case CX23885_BOARD_HAUPPAUGE_HVR1500Q: 997 case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
988 case CX23885_BOARD_HAUPPAUGE_HVR1800: 998 case CX23885_BOARD_HAUPPAUGE_HVR1800:
@@ -1001,7 +1011,7 @@ int cx23885_ir_init(struct cx23885_dev *dev)
1001 break; 1011 break;
1002 dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_888_IR); 1012 dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_888_IR);
1003 v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config, 1013 v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config,
1004 ir_pin_cfg_count, ir_pin_cfg); 1014 ir_rxtx_pin_cfg_count, ir_rxtx_pin_cfg);
1005 dev->pci_irqmask |= PCI_MSK_IR; 1015 dev->pci_irqmask |= PCI_MSK_IR;
1006 /* 1016 /*
1007 * For these boards we need to invert the Tx output via the 1017 * For these boards we need to invert the Tx output via the
@@ -1015,6 +1025,26 @@ int cx23885_ir_init(struct cx23885_dev *dev)
1015 params.shutdown = true; 1025 params.shutdown = true;
1016 v4l2_subdev_call(dev->sd_ir, ir, tx_s_parameters, &params); 1026 v4l2_subdev_call(dev->sd_ir, ir, tx_s_parameters, &params);
1017 break; 1027 break;
1028 case CX23885_BOARD_TEVII_S470:
1029 dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_AV_CORE);
1030 if (dev->sd_ir == NULL) {
1031 ret = -ENODEV;
1032 break;
1033 }
1034 v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config,
1035 ir_rx_pin_cfg_count, ir_rx_pin_cfg);
1036 dev->pci_irqmask |= PCI_MSK_AV_CORE;
1037 break;
1038 case CX23885_BOARD_HAUPPAUGE_HVR1250:
1039 dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_AV_CORE);
1040 if (dev->sd_ir == NULL) {
1041 ret = -ENODEV;
1042 break;
1043 }
1044 v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config,
1045 ir_rxtx_pin_cfg_count, ir_rxtx_pin_cfg);
1046 dev->pci_irqmask |= PCI_MSK_AV_CORE;
1047 break;
1018 case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: 1048 case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
1019 request_module("ir-kbd-i2c"); 1049 request_module("ir-kbd-i2c");
1020 break; 1050 break;
@@ -1033,6 +1063,13 @@ void cx23885_ir_fini(struct cx23885_dev *dev)
1033 cx23888_ir_remove(dev); 1063 cx23888_ir_remove(dev);
1034 dev->sd_ir = NULL; 1064 dev->sd_ir = NULL;
1035 break; 1065 break;
1066 case CX23885_BOARD_TEVII_S470:
1067 case CX23885_BOARD_HAUPPAUGE_HVR1250:
1068 dev->pci_irqmask &= ~PCI_MSK_AV_CORE;
1069 cx_clear(PCI_INT_MSK, PCI_MSK_AV_CORE);
1070 /* sd_ir is a duplicate pointer to the AV Core, just clear it */
1071 dev->sd_ir = NULL;
1072 break;
1036 } 1073 }
1037} 1074}
1038 1075
@@ -1044,6 +1081,11 @@ void cx23885_ir_pci_int_enable(struct cx23885_dev *dev)
1044 if (dev->sd_ir && (dev->pci_irqmask & PCI_MSK_IR)) 1081 if (dev->sd_ir && (dev->pci_irqmask & PCI_MSK_IR))
1045 cx_set(PCI_INT_MSK, PCI_MSK_IR); 1082 cx_set(PCI_INT_MSK, PCI_MSK_IR);
1046 break; 1083 break;
1084 case CX23885_BOARD_TEVII_S470:
1085 case CX23885_BOARD_HAUPPAUGE_HVR1250:
1086 if (dev->sd_ir && (dev->pci_irqmask & PCI_MSK_AV_CORE))
1087 cx_set(PCI_INT_MSK, PCI_MSK_AV_CORE);
1088 break;
1047 } 1089 }
1048} 1090}
1049 1091
@@ -1189,6 +1231,8 @@ void cx23885_card_setup(struct cx23885_dev *dev)
1189 case CX23885_BOARD_MAGICPRO_PROHDTVE2: 1231 case CX23885_BOARD_MAGICPRO_PROHDTVE2:
1190 case CX23885_BOARD_HAUPPAUGE_HVR1290: 1232 case CX23885_BOARD_HAUPPAUGE_HVR1290:
1191 case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200: 1233 case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200:
1234 case CX23885_BOARD_TEVII_S470:
1235 case CX23885_BOARD_HAUPPAUGE_HVR1250:
1192 dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, 1236 dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev,
1193 &dev->i2c_bus[2].i2c_adap, 1237 &dev->i2c_bus[2].i2c_adap,
1194 "cx25840", "cx25840", 0x88 >> 1, NULL); 1238 "cx25840", "cx25840", 0x88 >> 1, NULL);
diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c
index a74c0ab859ed..93e7afb98889 100644
--- a/drivers/media/video/cx23885/cx23885-core.c
+++ b/drivers/media/video/cx23885/cx23885-core.c
@@ -1650,7 +1650,7 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
1650 u32 ts1_status, ts1_mask; 1650 u32 ts1_status, ts1_mask;
1651 u32 ts2_status, ts2_mask; 1651 u32 ts2_status, ts2_mask;
1652 int vida_count = 0, ts1_count = 0, ts2_count = 0, handled = 0; 1652 int vida_count = 0, ts1_count = 0, ts2_count = 0, handled = 0;
1653 bool ir_handled = false; 1653 bool subdev_handled;
1654 1654
1655 pci_status = cx_read(PCI_INT_STAT); 1655 pci_status = cx_read(PCI_INT_STAT);
1656 pci_mask = cx_read(PCI_INT_MSK); 1656 pci_mask = cx_read(PCI_INT_MSK);
@@ -1681,7 +1681,7 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
1681 PCI_MSK_VID_C | PCI_MSK_VID_B | PCI_MSK_VID_A | 1681 PCI_MSK_VID_C | PCI_MSK_VID_B | PCI_MSK_VID_A |
1682 PCI_MSK_AUD_INT | PCI_MSK_AUD_EXT | 1682 PCI_MSK_AUD_INT | PCI_MSK_AUD_EXT |
1683 PCI_MSK_GPIO0 | PCI_MSK_GPIO1 | 1683 PCI_MSK_GPIO0 | PCI_MSK_GPIO1 |
1684 PCI_MSK_IR)) { 1684 PCI_MSK_AV_CORE | PCI_MSK_IR)) {
1685 1685
1686 if (pci_status & PCI_MSK_RISC_RD) 1686 if (pci_status & PCI_MSK_RISC_RD)
1687 dprintk(7, " (PCI_MSK_RISC_RD 0x%08x)\n", 1687 dprintk(7, " (PCI_MSK_RISC_RD 0x%08x)\n",
@@ -1731,6 +1731,10 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
1731 dprintk(7, " (PCI_MSK_GPIO1 0x%08x)\n", 1731 dprintk(7, " (PCI_MSK_GPIO1 0x%08x)\n",
1732 PCI_MSK_GPIO1); 1732 PCI_MSK_GPIO1);
1733 1733
1734 if (pci_status & PCI_MSK_AV_CORE)
1735 dprintk(7, " (PCI_MSK_AV_CORE 0x%08x)\n",
1736 PCI_MSK_AV_CORE);
1737
1734 if (pci_status & PCI_MSK_IR) 1738 if (pci_status & PCI_MSK_IR)
1735 dprintk(7, " (PCI_MSK_IR 0x%08x)\n", 1739 dprintk(7, " (PCI_MSK_IR 0x%08x)\n",
1736 PCI_MSK_IR); 1740 PCI_MSK_IR);
@@ -1765,9 +1769,19 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
1765 handled += cx23885_video_irq(dev, vida_status); 1769 handled += cx23885_video_irq(dev, vida_status);
1766 1770
1767 if (pci_status & PCI_MSK_IR) { 1771 if (pci_status & PCI_MSK_IR) {
1772 subdev_handled = false;
1768 v4l2_subdev_call(dev->sd_ir, core, interrupt_service_routine, 1773 v4l2_subdev_call(dev->sd_ir, core, interrupt_service_routine,
1769 pci_status, &ir_handled); 1774 pci_status, &subdev_handled);
1770 if (ir_handled) 1775 if (subdev_handled)
1776 handled++;
1777 }
1778
1779 if (pci_status & PCI_MSK_AV_CORE) {
1780 subdev_handled = false;
1781 v4l2_subdev_call(dev->sd_cx25840,
1782 core, interrupt_service_routine,
1783 pci_status, &subdev_handled);
1784 if (subdev_handled)
1771 handled++; 1785 handled++;
1772 } 1786 }
1773 1787
diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c
index 496d751ffdc8..3f924e21b957 100644
--- a/drivers/media/video/cx23885/cx23885-input.c
+++ b/drivers/media/video/cx23885/cx23885-input.c
@@ -99,8 +99,10 @@ void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events)
99 switch (dev->board) { 99 switch (dev->board) {
100 case CX23885_BOARD_HAUPPAUGE_HVR1850: 100 case CX23885_BOARD_HAUPPAUGE_HVR1850:
101 case CX23885_BOARD_HAUPPAUGE_HVR1290: 101 case CX23885_BOARD_HAUPPAUGE_HVR1290:
102 case CX23885_BOARD_TEVII_S470:
103 case CX23885_BOARD_HAUPPAUGE_HVR1250:
102 /* 104 /*
103 * The only board we handle right now. However other boards 105 * The only boards we handle right now. However other boards
104 * using the CX2388x integrated IR controller should be similar 106 * using the CX2388x integrated IR controller should be similar
105 */ 107 */
106 break; 108 break;
@@ -148,6 +150,7 @@ static int cx23885_input_ir_start(struct cx23885_dev *dev)
148 switch (dev->board) { 150 switch (dev->board) {
149 case CX23885_BOARD_HAUPPAUGE_HVR1850: 151 case CX23885_BOARD_HAUPPAUGE_HVR1850:
150 case CX23885_BOARD_HAUPPAUGE_HVR1290: 152 case CX23885_BOARD_HAUPPAUGE_HVR1290:
153 case CX23885_BOARD_HAUPPAUGE_HVR1250:
151 /* 154 /*
152 * The IR controller on this board only returns pulse widths. 155 * The IR controller on this board only returns pulse widths.
153 * Any other mode setting will fail to set up the device. 156 * Any other mode setting will fail to set up the device.
@@ -172,6 +175,37 @@ static int cx23885_input_ir_start(struct cx23885_dev *dev)
172 */ 175 */
173 params.invert_level = true; 176 params.invert_level = true;
174 break; 177 break;
178 case CX23885_BOARD_TEVII_S470:
179 /*
180 * The IR controller on this board only returns pulse widths.
181 * Any other mode setting will fail to set up the device.
182 */
183 params.mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
184 params.enable = true;
185 params.interrupt_enable = true;
186 params.shutdown = false;
187
188 /* Setup for a standard NEC protocol */
189 params.carrier_freq = 37917; /* Hz, 455 kHz/12 for NEC */
190 params.carrier_range_lower = 33000; /* Hz */
191 params.carrier_range_upper = 43000; /* Hz */
192 params.duty_cycle = 33; /* percent, 33 percent for NEC */
193
194 /*
195 * NEC max pulse width: (64/3)/(455 kHz/12) * 16 nec_units
196 * (64/3)/(455 kHz/12) * 16 nec_units * 1.375 = 12378022 ns
197 */
198 params.max_pulse_width = 12378022; /* ns */
199
200 /*
201 * NEC noise filter min width: (64/3)/(455 kHz/12) * 1 nec_unit
202 * (64/3)/(455 kHz/12) * 1 nec_units * 0.625 = 351648 ns
203 */
204 params.noise_filter_min_width = 351648; /* ns */
205
206 params.modulation = false;
207 params.invert_level = true;
208 break;
175 } 209 }
176 v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params); 210 v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
177 return 0; 211 return 0;
@@ -244,12 +278,20 @@ int cx23885_input_init(struct cx23885_dev *dev)
244 switch (dev->board) { 278 switch (dev->board) {
245 case CX23885_BOARD_HAUPPAUGE_HVR1850: 279 case CX23885_BOARD_HAUPPAUGE_HVR1850:
246 case CX23885_BOARD_HAUPPAUGE_HVR1290: 280 case CX23885_BOARD_HAUPPAUGE_HVR1290:
247 /* Integrated CX23888 IR controller */ 281 case CX23885_BOARD_HAUPPAUGE_HVR1250:
282 /* Integrated CX2388[58] IR controller */
248 driver_type = RC_DRIVER_IR_RAW; 283 driver_type = RC_DRIVER_IR_RAW;
249 allowed_protos = IR_TYPE_ALL; 284 allowed_protos = IR_TYPE_ALL;
250 /* The grey Hauppauge RC-5 remote */ 285 /* The grey Hauppauge RC-5 remote */
251 rc_map = RC_MAP_RC5_HAUPPAUGE_NEW; 286 rc_map = RC_MAP_RC5_HAUPPAUGE_NEW;
252 break; 287 break;
288 case CX23885_BOARD_TEVII_S470:
289 /* Integrated CX23885 IR controller */
290 driver_type = RC_DRIVER_IR_RAW;
291 allowed_protos = IR_TYPE_ALL;
292 /* A guess at the remote */
293 rc_map = RC_MAP_TEVII_NEC;
294 break;
253 default: 295 default:
254 return -ENODEV; 296 return -ENODEV;
255 } 297 }
diff --git a/drivers/media/video/cx23885/cx23885-reg.h b/drivers/media/video/cx23885/cx23885-reg.h
index c0bc9a068954..a28772db11f0 100644
--- a/drivers/media/video/cx23885/cx23885-reg.h
+++ b/drivers/media/video/cx23885/cx23885-reg.h
@@ -213,6 +213,7 @@ Channel manager Data Structure entry = 20 DWORD
213#define DEV_CNTRL2 0x00040000 213#define DEV_CNTRL2 0x00040000
214 214
215#define PCI_MSK_IR (1 << 28) 215#define PCI_MSK_IR (1 << 28)
216#define PCI_MSK_AV_CORE (1 << 27)
216#define PCI_MSK_GPIO1 (1 << 24) 217#define PCI_MSK_GPIO1 (1 << 24)
217#define PCI_MSK_GPIO0 (1 << 23) 218#define PCI_MSK_GPIO0 (1 << 23)
218#define PCI_MSK_APB_DMA (1 << 12) 219#define PCI_MSK_APB_DMA (1 << 12)