diff options
author | Andy Walls <awalls@md.metrocast.net> | 2010-07-18 23:41:41 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-08-08 22:42:55 -0400 |
commit | 98d109f90fc02ce8baf1c2471ffcf8d66fb0d8e6 (patch) | |
tree | df1a3191953696bcccc618a25f749ee8071565a9 /drivers/media/video/cx23885 | |
parent | d6b1850d3c49e66f17bbb67f964a48b11528f56b (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/video/cx23885')
-rw-r--r-- | drivers/media/video/cx23885/cx23885-cards.c | 52 | ||||
-rw-r--r-- | drivers/media/video/cx23885/cx23885-core.c | 22 | ||||
-rw-r--r-- | drivers/media/video/cx23885/cx23885-input.c | 46 | ||||
-rw-r--r-- | drivers/media/video/cx23885/cx23885-reg.h | 1 |
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 | ||
963 | int cx23885_ir_init(struct cx23885_dev *dev) | 963 | int 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, ¶ms); | 1026 | v4l2_subdev_call(dev->sd_ir, ir, tx_s_parameters, ¶ms); |
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, ¶ms); | 210 | v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, ¶ms); |
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) |