1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Driver for the Conexant CX23885/7/8 PCIe bridge 4 * 5 * Infrared remote control input device 6 * 7 * Most of this file is 8 * 9 * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net> 10 * 11 * However, the cx23885_input_{init,fini} functions contained herein are 12 * derived from Linux kernel files linux/media/video/.../...-input.c marked as: 13 * 14 * Copyright (C) 2008 <srinivasa.deevi at conexant dot com> 15 * Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> 16 * Markus Rechberger <mrechberger@gmail.com> 17 * Mauro Carvalho Chehab <mchehab@kernel.org> 18 * Sascha Sommer <saschasommer@freenet.de> 19 * Copyright (C) 2004, 2005 Chris Pascoe 20 * Copyright (C) 2003, 2004 Gerd Knorr 21 * Copyright (C) 2003 Pavel Machek 22 */ 23 24 #include "cx23885.h" 25 #include "cx23885-input.h" 26 27 #include <linux/slab.h> 28 #include <media/rc-core.h> 29 #include <media/v4l2-subdev.h> 30 31 #define MODULE_NAME "cx23885" 32 33 static void cx23885_input_process_measurements(struct cx23885_dev *dev, 34 bool overrun) 35 { 36 struct cx23885_kernel_ir *kernel_ir = dev->kernel_ir; 37 38 ssize_t num; 39 int count, i; 40 bool handle = false; 41 struct ir_raw_event ir_core_event[64]; 42 43 do { 44 num = 0; 45 v4l2_subdev_call(dev->sd_ir, ir, rx_read, (u8 *) ir_core_event, 46 sizeof(ir_core_event), &num); 47 48 count = num / sizeof(struct ir_raw_event); 49 50 for (i = 0; i < count; i++) { 51 ir_raw_event_store(kernel_ir->rc, 52 &ir_core_event[i]); 53 handle = true; 54 } 55 } while (num != 0); 56 57 if (overrun) 58 ir_raw_event_reset(kernel_ir->rc); 59 else if (handle) 60 ir_raw_event_handle(kernel_ir->rc); 61 } 62 63 void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events) 64 { 65 struct v4l2_subdev_ir_parameters params; 66 int overrun, data_available; 67 68 if (dev->sd_ir == NULL || events == 0) 69 return; 70 71 switch (dev->board) { 72 case CX23885_BOARD_HAUPPAUGE_HVR1270: 73 case CX23885_BOARD_HAUPPAUGE_HVR1850: 74 case CX23885_BOARD_HAUPPAUGE_HVR1290: 75 case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL: 76 case CX23885_BOARD_TEVII_S470: 77 case CX23885_BOARD_HAUPPAUGE_HVR1250: 78 case CX23885_BOARD_MYGICA_X8507: 79 case CX23885_BOARD_TBS_6980: 80 case CX23885_BOARD_TBS_6981: 81 case CX23885_BOARD_DVBSKY_T9580: 82 case CX23885_BOARD_DVBSKY_T980C: 83 case CX23885_BOARD_DVBSKY_S950C: 84 case CX23885_BOARD_TT_CT2_4500_CI: 85 case CX23885_BOARD_DVBSKY_S950: 86 case CX23885_BOARD_DVBSKY_S952: 87 case CX23885_BOARD_DVBSKY_T982: 88 case CX23885_BOARD_HAUPPAUGE_HVR1265_K4: 89 /* 90 * The only boards we handle right now. However other boards 91 * using the CX2388x integrated IR controller should be similar 92 */ 93 break; 94 default: 95 return; 96 } 97 98 overrun = events & (V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN | 99 V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN); 100 101 data_available = events & (V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED | 102 V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ); 103 104 if (overrun) { 105 /* If there was a FIFO overrun, stop the device */ 106 v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, ¶ms); 107 params.enable = false; 108 /* Mitigate race with cx23885_input_ir_stop() */ 109 params.shutdown = atomic_read(&dev->ir_input_stopping); 110 v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, ¶ms); 111 } 112 113 if (data_available) 114 cx23885_input_process_measurements(dev, overrun); 115 116 if (overrun) { 117 /* If there was a FIFO overrun, clear & restart the device */ 118 params.enable = true; 119 /* Mitigate race with cx23885_input_ir_stop() */ 120 params.shutdown = atomic_read(&dev->ir_input_stopping); 121 v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, ¶ms); 122 } 123 } 124 125 static int cx23885_input_ir_start(struct cx23885_dev *dev) 126 { 127 struct v4l2_subdev_ir_parameters params; 128 129 if (dev->sd_ir == NULL) 130 return -ENODEV; 131 132 atomic_set(&dev->ir_input_stopping, 0); 133 134 v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, ¶ms); 135 switch (dev->board) { 136 case CX23885_BOARD_HAUPPAUGE_HVR1270: 137 case CX23885_BOARD_HAUPPAUGE_HVR1850: 138 case CX23885_BOARD_HAUPPAUGE_HVR1290: 139 case CX23885_BOARD_HAUPPAUGE_HVR1250: 140 case CX23885_BOARD_MYGICA_X8507: 141 case CX23885_BOARD_DVBSKY_T9580: 142 case CX23885_BOARD_DVBSKY_T980C: 143 case CX23885_BOARD_DVBSKY_S950C: 144 case CX23885_BOARD_TT_CT2_4500_CI: 145 case CX23885_BOARD_DVBSKY_S950: 146 case CX23885_BOARD_DVBSKY_S952: 147 case CX23885_BOARD_DVBSKY_T982: 148 case CX23885_BOARD_HAUPPAUGE_HVR1265_K4: 149 /* 150 * The IR controller on this board only returns pulse widths. 151 * Any other mode setting will fail to set up the device. 152 */ 153 params.mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH; 154 params.enable = true; 155 params.interrupt_enable = true; 156 params.shutdown = false; 157 158 /* Setup for baseband compatible with both RC-5 and RC-6A */ 159 params.modulation = false; 160 /* RC-5: 2,222,222 ns = 1/36 kHz * 32 cycles * 2 marks * 1.25*/ 161 /* RC-6A: 3,333,333 ns = 1/36 kHz * 16 cycles * 6 marks * 1.25*/ 162 params.max_pulse_width = 3333333; /* ns */ 163 /* RC-5: 666,667 ns = 1/36 kHz * 32 cycles * 1 mark * 0.75 */ 164 /* RC-6A: 333,333 ns = 1/36 kHz * 16 cycles * 1 mark * 0.75 */ 165 params.noise_filter_min_width = 333333; /* ns */ 166 /* 167 * This board has inverted receive sense: 168 * mark is received as low logic level; 169 * falling edges are detected as rising edges; etc. 170 */ 171 params.invert_level = true; 172 break; 173 case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL: 174 case CX23885_BOARD_TEVII_S470: 175 case CX23885_BOARD_TBS_6980: 176 case CX23885_BOARD_TBS_6981: 177 /* 178 * The IR controller on this board only returns pulse widths. 179 * Any other mode setting will fail to set up the device. 180 */ 181 params.mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH; 182 params.enable = true; 183 params.interrupt_enable = true; 184 params.shutdown = false; 185 186 /* Setup for a standard NEC protocol */ 187 params.carrier_freq = 37917; /* Hz, 455 kHz/12 for NEC */ 188 params.carrier_range_lower = 33000; /* Hz */ 189 params.carrier_range_upper = 43000; /* Hz */ 190 params.duty_cycle = 33; /* percent, 33 percent for NEC */ 191 192 /* 193 * NEC max pulse width: (64/3)/(455 kHz/12) * 16 nec_units 194 * (64/3)/(455 kHz/12) * 16 nec_units * 1.375 = 12378022 ns 195 */ 196 params.max_pulse_width = 12378022; /* ns */ 197 198 /* 199 * NEC noise filter min width: (64/3)/(455 kHz/12) * 1 nec_unit 200 * (64/3)/(455 kHz/12) * 1 nec_units * 0.625 = 351648 ns 201 */ 202 params.noise_filter_min_width = 351648; /* ns */ 203 204 params.modulation = false; 205 params.invert_level = true; 206 break; 207 } 208 v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, ¶ms); 209 return 0; 210 } 211 212 static int cx23885_input_ir_open(struct rc_dev *rc) 213 { 214 struct cx23885_kernel_ir *kernel_ir = rc->priv; 215 216 if (kernel_ir->cx == NULL) 217 return -ENODEV; 218 219 return cx23885_input_ir_start(kernel_ir->cx); 220 } 221 222 static void cx23885_input_ir_stop(struct cx23885_dev *dev) 223 { 224 struct v4l2_subdev_ir_parameters params; 225 226 if (dev->sd_ir == NULL) 227 return; 228 229 /* 230 * Stop the sd_ir subdevice from generating notifications and 231 * scheduling work. 232 * It is shutdown this way in order to mitigate a race with 233 * cx23885_input_rx_work_handler() in the overrun case, which could 234 * re-enable the subdevice. 235 */ 236 atomic_set(&dev->ir_input_stopping, 1); 237 v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, ¶ms); 238 while (params.shutdown == false) { 239 params.enable = false; 240 params.interrupt_enable = false; 241 params.shutdown = true; 242 v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, ¶ms); 243 v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, ¶ms); 244 } 245 flush_work(&dev->cx25840_work); 246 flush_work(&dev->ir_rx_work); 247 flush_work(&dev->ir_tx_work); 248 } 249 250 static void cx23885_input_ir_close(struct rc_dev *rc) 251 { 252 struct cx23885_kernel_ir *kernel_ir = rc->priv; 253 254 if (kernel_ir->cx != NULL) 255 cx23885_input_ir_stop(kernel_ir->cx); 256 } 257 258 int cx23885_input_init(struct cx23885_dev *dev) 259 { 260 struct cx23885_kernel_ir *kernel_ir; 261 struct rc_dev *rc; 262 char *rc_map; 263 u64 allowed_protos; 264 265 int ret; 266 267 /* 268 * If the IR device (hardware registers, chip, GPIO lines, etc.) isn't 269 * encapsulated in a v4l2_subdev, then I'm not going to deal with it. 270 */ 271 if (dev->sd_ir == NULL) 272 return -ENODEV; 273 274 switch (dev->board) { 275 case CX23885_BOARD_HAUPPAUGE_HVR1270: 276 case CX23885_BOARD_HAUPPAUGE_HVR1850: 277 case CX23885_BOARD_HAUPPAUGE_HVR1290: 278 case CX23885_BOARD_HAUPPAUGE_HVR1250: 279 case CX23885_BOARD_HAUPPAUGE_HVR1265_K4: 280 /* Integrated CX2388[58] IR controller */ 281 allowed_protos = RC_PROTO_BIT_ALL_IR_DECODER; 282 /* The grey Hauppauge RC-5 remote */ 283 rc_map = RC_MAP_HAUPPAUGE; 284 break; 285 case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL: 286 /* Integrated CX23885 IR controller */ 287 allowed_protos = RC_PROTO_BIT_ALL_IR_DECODER; 288 /* The grey Terratec remote with orange buttons */ 289 rc_map = RC_MAP_NEC_TERRATEC_CINERGY_XS; 290 break; 291 case CX23885_BOARD_TEVII_S470: 292 /* Integrated CX23885 IR controller */ 293 allowed_protos = RC_PROTO_BIT_ALL_IR_DECODER; 294 /* A guess at the remote */ 295 rc_map = RC_MAP_TEVII_NEC; 296 break; 297 case CX23885_BOARD_MYGICA_X8507: 298 /* Integrated CX23885 IR controller */ 299 allowed_protos = RC_PROTO_BIT_ALL_IR_DECODER; 300 /* A guess at the remote */ 301 rc_map = RC_MAP_TOTAL_MEDIA_IN_HAND_02; 302 break; 303 case CX23885_BOARD_TBS_6980: 304 case CX23885_BOARD_TBS_6981: 305 /* Integrated CX23885 IR controller */ 306 allowed_protos = RC_PROTO_BIT_ALL_IR_DECODER; 307 /* A guess at the remote */ 308 rc_map = RC_MAP_TBS_NEC; 309 break; 310 case CX23885_BOARD_DVBSKY_T9580: 311 case CX23885_BOARD_DVBSKY_T980C: 312 case CX23885_BOARD_DVBSKY_S950C: 313 case CX23885_BOARD_DVBSKY_S950: 314 case CX23885_BOARD_DVBSKY_S952: 315 case CX23885_BOARD_DVBSKY_T982: 316 /* Integrated CX23885 IR controller */ 317 allowed_protos = RC_PROTO_BIT_ALL_IR_DECODER; 318 rc_map = RC_MAP_DVBSKY; 319 break; 320 case CX23885_BOARD_TT_CT2_4500_CI: 321 /* Integrated CX23885 IR controller */ 322 allowed_protos = RC_PROTO_BIT_ALL_IR_DECODER; 323 rc_map = RC_MAP_TT_1500; 324 break; 325 default: 326 return -ENODEV; 327 } 328 329 /* cx23885 board instance kernel IR state */ 330 kernel_ir = kzalloc(sizeof(struct cx23885_kernel_ir), GFP_KERNEL); 331 if (kernel_ir == NULL) 332 return -ENOMEM; 333 334 kernel_ir->cx = dev; 335 kernel_ir->name = kasprintf(GFP_KERNEL, "cx23885 IR (%s)", 336 cx23885_boards[dev->board].name); 337 if (!kernel_ir->name) { 338 ret = -ENOMEM; 339 goto err_out_free; 340 } 341 342 kernel_ir->phys = kasprintf(GFP_KERNEL, "pci-%s/ir0", 343 pci_name(dev->pci)); 344 if (!kernel_ir->phys) { 345 ret = -ENOMEM; 346 goto err_out_free_name; 347 } 348 349 /* input device */ 350 rc = rc_allocate_device(RC_DRIVER_IR_RAW); 351 if (!rc) { 352 ret = -ENOMEM; 353 goto err_out_free_phys; 354 } 355 356 kernel_ir->rc = rc; 357 rc->device_name = kernel_ir->name; 358 rc->input_phys = kernel_ir->phys; 359 rc->input_id.bustype = BUS_PCI; 360 rc->input_id.version = 1; 361 if (dev->pci->subsystem_vendor) { 362 rc->input_id.vendor = dev->pci->subsystem_vendor; 363 rc->input_id.product = dev->pci->subsystem_device; 364 } else { 365 rc->input_id.vendor = dev->pci->vendor; 366 rc->input_id.product = dev->pci->device; 367 } 368 rc->dev.parent = &dev->pci->dev; 369 rc->allowed_protocols = allowed_protos; 370 rc->priv = kernel_ir; 371 rc->open = cx23885_input_ir_open; 372 rc->close = cx23885_input_ir_close; 373 rc->map_name = rc_map; 374 rc->driver_name = MODULE_NAME; 375 376 /* Go */ 377 dev->kernel_ir = kernel_ir; 378 ret = rc_register_device(rc); 379 if (ret) 380 goto err_out_stop; 381 382 return 0; 383 384 err_out_stop: 385 cx23885_input_ir_stop(dev); 386 dev->kernel_ir = NULL; 387 rc_free_device(rc); 388 err_out_free_phys: 389 kfree(kernel_ir->phys); 390 err_out_free_name: 391 kfree(kernel_ir->name); 392 err_out_free: 393 kfree(kernel_ir); 394 return ret; 395 } 396 397 void cx23885_input_fini(struct cx23885_dev *dev) 398 { 399 /* Always stop the IR hardware from generating interrupts */ 400 cx23885_input_ir_stop(dev); 401 402 if (dev->kernel_ir == NULL) 403 return; 404 rc_unregister_device(dev->kernel_ir->rc); 405 kfree(dev->kernel_ir->phys); 406 kfree(dev->kernel_ir->name); 407 kfree(dev->kernel_ir); 408 dev->kernel_ir = NULL; 409 } 410