aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx23885/cx23885-input.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/cx23885/cx23885-input.c')
-rw-r--r--drivers/media/video/cx23885/cx23885-input.c317
1 files changed, 109 insertions, 208 deletions
diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c
index 5de6ba98f7a8..d0b1613ede2f 100644
--- a/drivers/media/video/cx23885/cx23885-input.c
+++ b/drivers/media/video/cx23885/cx23885-input.c
@@ -37,161 +37,55 @@
37 37
38#include <linux/input.h> 38#include <linux/input.h>
39#include <linux/slab.h> 39#include <linux/slab.h>
40#include <media/ir-common.h> 40#include <media/ir-core.h>
41#include <media/v4l2-subdev.h> 41#include <media/v4l2-subdev.h>
42 42
43#include "cx23885.h" 43#include "cx23885.h"
44 44
45#define RC5_BITS 14
46#define RC5_HALF_BITS (2*RC5_BITS)
47#define RC5_HALF_BITS_MASK ((1 << RC5_HALF_BITS) - 1)
48
49#define RC5_START_BITS_NORMAL 0x3 /* Command range 0 - 63 */
50#define RC5_START_BITS_EXTENDED 0x2 /* Command range 64 - 127 */
51
52#define RC5_EXTENDED_COMMAND_OFFSET 64
53
54#define MODULE_NAME "cx23885" 45#define MODULE_NAME "cx23885"
55 46
56static inline unsigned int rc5_command(u32 rc5_baseband) 47static void convert_measurement(u32 x, struct ir_raw_event *y)
57{ 48{
58 return RC5_INSTR(rc5_baseband) + 49 if (x == V4L2_SUBDEV_IR_PULSE_RX_SEQ_END) {
59 ((RC5_START(rc5_baseband) == RC5_START_BITS_EXTENDED) 50 y->pulse = false;
60 ? RC5_EXTENDED_COMMAND_OFFSET : 0); 51 y->duration = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS;
61}
62
63static void cx23885_input_process_raw_rc5(struct cx23885_dev *dev)
64{
65 struct card_ir *ir_input = dev->ir_input;
66 unsigned int code, command;
67 u32 rc5;
68
69 /* Ignore codes that are too short to be valid RC-5 */
70 if (ir_input->last_bit < (RC5_HALF_BITS - 1))
71 return;
72
73 /* The library has the manchester coding backwards; XOR to adapt. */
74 code = (ir_input->code & RC5_HALF_BITS_MASK) ^ RC5_HALF_BITS_MASK;
75 rc5 = ir_rc5_decode(code);
76
77 switch (RC5_START(rc5)) {
78 case RC5_START_BITS_NORMAL:
79 break;
80 case RC5_START_BITS_EXTENDED:
81 /* Don't allow if the remote only emits standard commands */
82 if (ir_input->start == RC5_START_BITS_NORMAL)
83 return;
84 break;
85 default:
86 return; 52 return;
87 } 53 }
88 54
89 if (ir_input->addr != RC5_ADDR(rc5)) 55 y->pulse = (x & V4L2_SUBDEV_IR_PULSE_LEVEL_MASK) ? true : false;
90 return; 56 y->duration = x & V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS;
91
92 /* Don't generate a keypress for RC-5 auto-repeated keypresses */
93 command = rc5_command(rc5);
94 if (RC5_TOGGLE(rc5) != RC5_TOGGLE(ir_input->last_rc5) ||
95 command != rc5_command(ir_input->last_rc5) ||
96 /* Catch T == 0, CMD == 0 (e.g. '0') as first keypress after init */
97 RC5_START(ir_input->last_rc5) == 0) {
98 /* This keypress is differnet: not an auto repeat */
99 ir_input_nokey(ir_input->dev, &ir_input->ir);
100 ir_input_keydown(ir_input->dev, &ir_input->ir, command);
101 }
102 ir_input->last_rc5 = rc5;
103
104 /* Schedule when we should do the key up event: ir_input_nokey() */
105 mod_timer(&ir_input->timer_keyup,
106 jiffies + msecs_to_jiffies(ir_input->rc5_key_timeout));
107} 57}
108 58
109static void cx23885_input_next_pulse_width_rc5(struct cx23885_dev *dev, 59static void cx23885_input_process_measurements(struct cx23885_dev *dev,
110 u32 ns_pulse) 60 bool overrun)
111{ 61{
112 const int rc5_quarterbit_ns = 444444; /* 32 cycles/36 kHz/2 = 444 us */ 62 struct cx23885_kernel_ir *kernel_ir = dev->kernel_ir;
113 struct card_ir *ir_input = dev->ir_input; 63 struct ir_raw_event kernel_ir_event;
114 int i, level, quarterbits, halfbits;
115
116 if (!ir_input->active) {
117 ir_input->active = 1;
118 /* assume an initial space that we may not detect or measure */
119 ir_input->code = 0;
120 ir_input->last_bit = 0;
121 }
122 64
123 if (ns_pulse == V4L2_SUBDEV_IR_PULSE_RX_SEQ_END) { 65 u32 sd_ir_data[64];
124 ir_input->last_bit++; /* Account for the final space */ 66 ssize_t num;
125 ir_input->active = 0;
126 cx23885_input_process_raw_rc5(dev);
127 return;
128 }
129
130 level = (ns_pulse & V4L2_SUBDEV_IR_PULSE_LEVEL_MASK) ? 1 : 0;
131
132 /* Skip any leading space to sync to the start bit */
133 if (ir_input->last_bit == 0 && level == 0)
134 return;
135
136 /*
137 * With valid RC-5 we can get up to two consecutive half-bits in a
138 * single pulse measurment. Experiments have shown that the duration
139 * of a half-bit can vary. Make sure we always end up with an even
140 * number of quarter bits at the same level (mark or space).
141 */
142 ns_pulse &= V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS;
143 quarterbits = ns_pulse / rc5_quarterbit_ns;
144 if (quarterbits & 1)
145 quarterbits++;
146 halfbits = quarterbits / 2;
147
148 for (i = 0; i < halfbits; i++) {
149 ir_input->last_bit++;
150 ir_input->code |= (level << ir_input->last_bit);
151
152 if (ir_input->last_bit >= RC5_HALF_BITS-1) {
153 ir_input->active = 0;
154 cx23885_input_process_raw_rc5(dev);
155 /*
156 * If level is 1, a leading mark is invalid for RC5.
157 * If level is 0, we scan past extra intial space.
158 * Either way we don't want to reactivate collecting
159 * marks or spaces here with any left over half-bits.
160 */
161 break;
162 }
163 }
164}
165
166static void cx23885_input_process_pulse_widths_rc5(struct cx23885_dev *dev,
167 bool add_eom)
168{
169 struct card_ir *ir_input = dev->ir_input;
170 struct ir_input_state *ir_input_state = &ir_input->ir;
171
172 u32 ns_pulse[RC5_HALF_BITS+1];
173 ssize_t num = 0;
174 int count, i; 67 int count, i;
68 bool handle = false;
175 69
176 do { 70 do {
177 v4l2_subdev_call(dev->sd_ir, ir, rx_read, (u8 *) ns_pulse, 71 num = 0;
178 sizeof(ns_pulse), &num); 72 v4l2_subdev_call(dev->sd_ir, ir, rx_read, (u8 *) sd_ir_data,
73 sizeof(sd_ir_data), &num);
179 74
180 count = num / sizeof(u32); 75 count = num / sizeof(u32);
181 76
182 /* Append an end of Rx seq, if the caller requested */ 77 for (i = 0; i < count; i++) {
183 if (add_eom && count < ARRAY_SIZE(ns_pulse)) { 78 convert_measurement(sd_ir_data[i], &kernel_ir_event);
184 ns_pulse[count] = V4L2_SUBDEV_IR_PULSE_RX_SEQ_END; 79 ir_raw_event_store(kernel_ir->inp_dev,
185 count++; 80 &kernel_ir_event);
81 handle = true;
186 } 82 }
187
188 /* Just drain the Rx FIFO, if we're called, but not RC-5 */
189 if (ir_input_state->ir_type != IR_TYPE_RC5)
190 continue;
191
192 for (i = 0; i < count; i++)
193 cx23885_input_next_pulse_width_rc5(dev, ns_pulse[i]);
194 } while (num != 0); 83 } while (num != 0);
84
85 if (overrun)
86 ir_raw_event_reset(kernel_ir->inp_dev);
87 else if (handle)
88 ir_raw_event_handle(kernel_ir->inp_dev);
195} 89}
196 90
197void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events) 91void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events)
@@ -230,7 +124,7 @@ void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events)
230 } 124 }
231 125
232 if (data_available) 126 if (data_available)
233 cx23885_input_process_pulse_widths_rc5(dev, overrun); 127 cx23885_input_process_measurements(dev, overrun);
234 128
235 if (overrun) { 129 if (overrun) {
236 /* If there was a FIFO overrun, clear & restart the device */ 130 /* If there was a FIFO overrun, clear & restart the device */
@@ -241,34 +135,15 @@ void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events)
241 } 135 }
242} 136}
243 137
244static void cx23885_input_ir_start(struct cx23885_dev *dev) 138static int cx23885_input_ir_start(struct cx23885_dev *dev)
245{ 139{
246 struct card_ir *ir_input = dev->ir_input;
247 struct ir_input_state *ir_input_state = &ir_input->ir;
248 struct v4l2_subdev_ir_parameters params; 140 struct v4l2_subdev_ir_parameters params;
249 141
250 if (dev->sd_ir == NULL) 142 if (dev->sd_ir == NULL)
251 return; 143 return -ENODEV;
252 144
253 atomic_set(&dev->ir_input_stopping, 0); 145 atomic_set(&dev->ir_input_stopping, 0);
254 146
255 /* keyup timer set up, if needed */
256 switch (dev->board) {
257 case CX23885_BOARD_HAUPPAUGE_HVR1850:
258 case CX23885_BOARD_HAUPPAUGE_HVR1290:
259 setup_timer(&ir_input->timer_keyup,
260 ir_rc5_timer_keyup, /* Not actually RC-5 specific */
261 (unsigned long) ir_input);
262 if (ir_input_state->ir_type == IR_TYPE_RC5) {
263 /*
264 * RC-5 repeats a held key every
265 * 64 bits * (2 * 32/36000) sec/bit = 113.778 ms
266 */
267 ir_input->rc5_key_timeout = 115;
268 }
269 break;
270 }
271
272 v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params); 147 v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
273 switch (dev->board) { 148 switch (dev->board) {
274 case CX23885_BOARD_HAUPPAUGE_HVR1850: 149 case CX23885_BOARD_HAUPPAUGE_HVR1850:
@@ -299,11 +174,21 @@ static void cx23885_input_ir_start(struct cx23885_dev *dev)
299 break; 174 break;
300 } 175 }
301 v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params); 176 v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
177 return 0;
178}
179
180static int cx23885_input_ir_open(void *priv)
181{
182 struct cx23885_kernel_ir *kernel_ir = priv;
183
184 if (kernel_ir->cx == NULL)
185 return -ENODEV;
186
187 return cx23885_input_ir_start(kernel_ir->cx);
302} 188}
303 189
304static void cx23885_input_ir_stop(struct cx23885_dev *dev) 190static void cx23885_input_ir_stop(struct cx23885_dev *dev)
305{ 191{
306 struct card_ir *ir_input = dev->ir_input;
307 struct v4l2_subdev_ir_parameters params; 192 struct v4l2_subdev_ir_parameters params;
308 193
309 if (dev->sd_ir == NULL) 194 if (dev->sd_ir == NULL)
@@ -327,21 +212,26 @@ static void cx23885_input_ir_stop(struct cx23885_dev *dev)
327 } 212 }
328 213
329 flush_scheduled_work(); 214 flush_scheduled_work();
215}
330 216
331 switch (dev->board) { 217static void cx23885_input_ir_close(void *priv)
332 case CX23885_BOARD_HAUPPAUGE_HVR1850: 218{
333 case CX23885_BOARD_HAUPPAUGE_HVR1290: 219 struct cx23885_kernel_ir *kernel_ir = priv;
334 del_timer_sync(&ir_input->timer_keyup); 220
335 break; 221 if (kernel_ir->cx != NULL)
336 } 222 cx23885_input_ir_stop(kernel_ir->cx);
337} 223}
338 224
339int cx23885_input_init(struct cx23885_dev *dev) 225int cx23885_input_init(struct cx23885_dev *dev)
340{ 226{
341 struct card_ir *ir; 227 struct cx23885_kernel_ir *kernel_ir;
342 struct input_dev *input_dev; 228 struct input_dev *inp_dev;
343 char *ir_codes = NULL; 229 struct ir_dev_props *props;
344 int ir_type, ir_addr, ir_start; 230
231 char *rc_map;
232 enum rc_driver_type driver_type;
233 unsigned long allowed_protos;
234
345 int ret; 235 int ret;
346 236
347 /* 237 /*
@@ -354,53 +244,59 @@ int cx23885_input_init(struct cx23885_dev *dev)
354 switch (dev->board) { 244 switch (dev->board) {
355 case CX23885_BOARD_HAUPPAUGE_HVR1850: 245 case CX23885_BOARD_HAUPPAUGE_HVR1850:
356 case CX23885_BOARD_HAUPPAUGE_HVR1290: 246 case CX23885_BOARD_HAUPPAUGE_HVR1290:
357 /* Parameters for the grey Hauppauge remote for the HVR-1850 */ 247 /* Integrated CX23888 IR controller */
358 ir_codes = RC_MAP_HAUPPAUGE_NEW; 248 driver_type = RC_DRIVER_IR_RAW;
359 ir_type = IR_TYPE_RC5; 249 allowed_protos = IR_TYPE_ALL;
360 ir_addr = 0x1e; /* RC-5 system bits emitted by the remote */ 250 /* The grey Hauppauge RC-5 remote */
361 ir_start = RC5_START_BITS_NORMAL; /* A basic RC-5 remote */ 251 rc_map = RC_MAP_RC5_HAUPPAUGE_NEW;
362 break; 252 break;
363 } 253 default:
364 if (ir_codes == NULL)
365 return -ENODEV; 254 return -ENODEV;
366
367 ir = kzalloc(sizeof(*ir), GFP_KERNEL);
368 input_dev = input_allocate_device();
369 if (!ir || !input_dev) {
370 ret = -ENOMEM;
371 goto err_out_free;
372 } 255 }
373 256
374 ir->dev = input_dev; 257 /* cx23885 board instance kernel IR state */
375 ir->addr = ir_addr; 258 kernel_ir = kzalloc(sizeof(struct cx23885_kernel_ir), GFP_KERNEL);
376 ir->start = ir_start; 259 if (kernel_ir == NULL)
260 return -ENOMEM;
377 261
378 /* init input device */ 262 kernel_ir->cx = dev;
379 snprintf(ir->name, sizeof(ir->name), "cx23885 IR (%s)", 263 kernel_ir->name = kasprintf(GFP_KERNEL, "cx23885 IR (%s)",
380 cx23885_boards[dev->board].name); 264 cx23885_boards[dev->board].name);
381 snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(dev->pci)); 265 kernel_ir->phys = kasprintf(GFP_KERNEL, "pci-%s/ir0",
266 pci_name(dev->pci));
382 267
383 ret = ir_input_init(input_dev, &ir->ir, ir_type); 268 /* input device */
384 if (ret < 0) 269 inp_dev = input_allocate_device();
270 if (inp_dev == NULL) {
271 ret = -ENOMEM;
385 goto err_out_free; 272 goto err_out_free;
273 }
386 274
387 input_dev->name = ir->name; 275 kernel_ir->inp_dev = inp_dev;
388 input_dev->phys = ir->phys; 276 inp_dev->name = kernel_ir->name;
389 input_dev->id.bustype = BUS_PCI; 277 inp_dev->phys = kernel_ir->phys;
390 input_dev->id.version = 1; 278 inp_dev->id.bustype = BUS_PCI;
279 inp_dev->id.version = 1;
391 if (dev->pci->subsystem_vendor) { 280 if (dev->pci->subsystem_vendor) {
392 input_dev->id.vendor = dev->pci->subsystem_vendor; 281 inp_dev->id.vendor = dev->pci->subsystem_vendor;
393 input_dev->id.product = dev->pci->subsystem_device; 282 inp_dev->id.product = dev->pci->subsystem_device;
394 } else { 283 } else {
395 input_dev->id.vendor = dev->pci->vendor; 284 inp_dev->id.vendor = dev->pci->vendor;
396 input_dev->id.product = dev->pci->device; 285 inp_dev->id.product = dev->pci->device;
397 } 286 }
398 input_dev->dev.parent = &dev->pci->dev; 287 inp_dev->dev.parent = &dev->pci->dev;
399 288
400 dev->ir_input = ir; 289 /* kernel ir device properties */
401 cx23885_input_ir_start(dev); 290 props = &kernel_ir->props;
402 291 props->driver_type = driver_type;
403 ret = ir_input_register(ir->dev, ir_codes, NULL, MODULE_NAME); 292 props->allowed_protos = allowed_protos;
293 props->priv = kernel_ir;
294 props->open = cx23885_input_ir_open;
295 props->close = cx23885_input_ir_close;
296
297 /* Go */
298 dev->kernel_ir = kernel_ir;
299 ret = ir_input_register(inp_dev, rc_map, props, MODULE_NAME);
404 if (ret) 300 if (ret)
405 goto err_out_stop; 301 goto err_out_stop;
406 302
@@ -408,9 +304,12 @@ int cx23885_input_init(struct cx23885_dev *dev)
408 304
409err_out_stop: 305err_out_stop:
410 cx23885_input_ir_stop(dev); 306 cx23885_input_ir_stop(dev);
411 dev->ir_input = NULL; 307 dev->kernel_ir = NULL;
308 /* TODO: double check clean-up of kernel_ir->inp_dev */
412err_out_free: 309err_out_free:
413 kfree(ir); 310 kfree(kernel_ir->phys);
311 kfree(kernel_ir->name);
312 kfree(kernel_ir);
414 return ret; 313 return ret;
415} 314}
416 315
@@ -419,9 +318,11 @@ void cx23885_input_fini(struct cx23885_dev *dev)
419 /* Always stop the IR hardware from generating interrupts */ 318 /* Always stop the IR hardware from generating interrupts */
420 cx23885_input_ir_stop(dev); 319 cx23885_input_ir_stop(dev);
421 320
422 if (dev->ir_input == NULL) 321 if (dev->kernel_ir == NULL)
423 return; 322 return;
424 ir_input_unregister(dev->ir_input->dev); 323 ir_input_unregister(dev->kernel_ir->inp_dev);
425 kfree(dev->ir_input); 324 kfree(dev->kernel_ir->phys);
426 dev->ir_input = NULL; 325 kfree(dev->kernel_ir->name);
326 kfree(dev->kernel_ir);
327 dev->kernel_ir = NULL;
427} 328}