diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-12-14 00:54:22 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-02-26 13:10:23 -0500 |
commit | 950b0f5a0bf764663a6aa4397d105ad571c64a83 (patch) | |
tree | 74dcfdfc52a7594c300dc63ffbf42744a8ef715c /drivers/media/video/em28xx/em28xx-input.c | |
parent | 09b01b90eb08769a64159ff4f81efe4badf6a49b (diff) |
V4L/DVB (13637): em28xx: allow changing keycode table protocol
Experimental patch to allow changing the IR protocol. Currently, it support
changing between RC-5 and NEC protocols.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/em28xx/em28xx-input.c')
-rw-r--r-- | drivers/media/video/em28xx/em28xx-input.c | 80 |
1 files changed, 54 insertions, 26 deletions
diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index fbfbab6841cd..ebb75a867f03 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c | |||
@@ -75,6 +75,10 @@ struct em28xx_IR { | |||
75 | unsigned int repeat_interval; | 75 | unsigned int repeat_interval; |
76 | 76 | ||
77 | int (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *); | 77 | int (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *); |
78 | |||
79 | /* IR device properties */ | ||
80 | |||
81 | struct ir_dev_props props; | ||
78 | }; | 82 | }; |
79 | 83 | ||
80 | /********************************************************** | 84 | /********************************************************** |
@@ -336,35 +340,25 @@ static void em28xx_ir_stop(struct em28xx_IR *ir) | |||
336 | cancel_delayed_work_sync(&ir->work); | 340 | cancel_delayed_work_sync(&ir->work); |
337 | } | 341 | } |
338 | 342 | ||
339 | int em28xx_ir_init(struct em28xx *dev) | 343 | int em28xx_ir_change_protocol(void *priv, enum ir_type ir_type) |
340 | { | 344 | { |
341 | struct em28xx_IR *ir; | 345 | int rc = 0; |
342 | struct input_dev *input_dev; | 346 | struct em28xx_IR *ir = priv; |
343 | u8 ir_config; | 347 | struct em28xx *dev = ir->dev; |
344 | int err = -ENOMEM; | 348 | u8 ir_config = EM2874_IR_RC5; |
345 | |||
346 | if (dev->board.ir_codes == NULL) { | ||
347 | /* No remote control support */ | ||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); | ||
352 | input_dev = input_allocate_device(); | ||
353 | if (!ir || !input_dev) | ||
354 | goto err_out_free; | ||
355 | |||
356 | ir->input = input_dev; | ||
357 | ir_config = EM2874_IR_RC5; | ||
358 | 349 | ||
359 | /* Adjust xclk based o IR table for RC5/NEC tables */ | 350 | /* Adjust xclk based o IR table for RC5/NEC tables */ |
360 | if (dev->board.ir_codes->ir_type == IR_TYPE_RC5) { | 351 | |
352 | if (ir_type == IR_TYPE_RC5) { | ||
361 | dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE; | 353 | dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE; |
362 | ir->full_code = 1; | 354 | ir->full_code = 1; |
363 | } else if (dev->board.ir_codes->ir_type == IR_TYPE_NEC) { | 355 | } else if (ir_type == IR_TYPE_NEC) { |
364 | dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE; | 356 | dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE; |
365 | ir_config = EM2874_IR_NEC; | 357 | ir_config = EM2874_IR_NEC; |
366 | ir->full_code = 1; | 358 | ir->full_code = 1; |
367 | } | 359 | } else |
360 | rc = -EINVAL; | ||
361 | |||
368 | em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk, | 362 | em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk, |
369 | EM28XX_XCLK_IR_RC5_MODE); | 363 | EM28XX_XCLK_IR_RC5_MODE); |
370 | 364 | ||
@@ -380,9 +374,42 @@ int em28xx_ir_init(struct em28xx *dev) | |||
380 | break; | 374 | break; |
381 | default: | 375 | default: |
382 | printk("Unrecognized em28xx chip id: IR not supported\n"); | 376 | printk("Unrecognized em28xx chip id: IR not supported\n"); |
383 | goto err_out_free; | 377 | rc = -EINVAL; |
378 | } | ||
379 | |||
380 | return rc; | ||
381 | } | ||
382 | |||
383 | int em28xx_ir_init(struct em28xx *dev) | ||
384 | { | ||
385 | struct em28xx_IR *ir; | ||
386 | struct input_dev *input_dev; | ||
387 | int err = -ENOMEM; | ||
388 | |||
389 | if (dev->board.ir_codes == NULL) { | ||
390 | /* No remote control support */ | ||
391 | return 0; | ||
384 | } | 392 | } |
385 | 393 | ||
394 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); | ||
395 | input_dev = input_allocate_device(); | ||
396 | if (!ir || !input_dev) | ||
397 | goto err_out_free; | ||
398 | |||
399 | /* record handles to ourself */ | ||
400 | ir->dev = dev; | ||
401 | dev->ir = ir; | ||
402 | |||
403 | ir->input = input_dev; | ||
404 | |||
405 | /* | ||
406 | * em2874 supports more protocols. For now, let's just announce | ||
407 | * the two protocols that were already tested | ||
408 | */ | ||
409 | ir->props.allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; | ||
410 | ir->props.priv = ir; | ||
411 | ir->props.change_protocol = em28xx_ir_change_protocol; | ||
412 | |||
386 | /* This is how often we ask the chip for IR information */ | 413 | /* This is how often we ask the chip for IR information */ |
387 | ir->polling = 100; /* ms */ | 414 | ir->polling = 100; /* ms */ |
388 | 415 | ||
@@ -393,6 +420,8 @@ int em28xx_ir_init(struct em28xx *dev) | |||
393 | usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); | 420 | usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); |
394 | strlcat(ir->phys, "/input0", sizeof(ir->phys)); | 421 | strlcat(ir->phys, "/input0", sizeof(ir->phys)); |
395 | 422 | ||
423 | /* Set IR protocol */ | ||
424 | em28xx_ir_change_protocol(ir, dev->board.ir_codes->ir_type); | ||
396 | err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER); | 425 | err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER); |
397 | if (err < 0) | 426 | if (err < 0) |
398 | goto err_out_free; | 427 | goto err_out_free; |
@@ -405,14 +434,13 @@ int em28xx_ir_init(struct em28xx *dev) | |||
405 | input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct); | 434 | input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct); |
406 | 435 | ||
407 | input_dev->dev.parent = &dev->udev->dev; | 436 | input_dev->dev.parent = &dev->udev->dev; |
408 | /* record handles to ourself */ | 437 | |
409 | ir->dev = dev; | ||
410 | dev->ir = ir; | ||
411 | 438 | ||
412 | em28xx_ir_start(ir); | 439 | em28xx_ir_start(ir); |
413 | 440 | ||
414 | /* all done */ | 441 | /* all done */ |
415 | err = ir_input_register(ir->input, dev->board.ir_codes, NULL); | 442 | err = ir_input_register(ir->input, dev->board.ir_codes, |
443 | &ir->props); | ||
416 | if (err) | 444 | if (err) |
417 | goto err_out_stop; | 445 | goto err_out_stop; |
418 | 446 | ||