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