diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-04-07 21:57:04 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-05-19 11:57:00 -0400 |
commit | c373cabfbbb7631526003f17d470c0d1e5915a4c (patch) | |
tree | a7182689854e29355ed7f3934fe53e29699b7be9 /drivers/media/video/em28xx | |
parent | 9b09df51b8c2b4615376e5ada3e2eb7eeed3cf5d (diff) |
V4L/DVB: em28xx: fix a regression caused by the rc-map changes
The patch that adds the rc-map changes didn't take into account that an
a table with IR_TYPE_UNKNOWN would make change_protocol to return -EINVAL.
As this function is fundamental to initialize some data, including a
callback to the getkey function, this caused the driver to stop working,
hanging the machine most of the times.
The fix were simply to add a handler for the IR type, but, to avoid further
issues, explicitly call change_protocol and handle the error before
initializing the IR. Also, let input_dev to start/stop IR handling,
after the opening of the input device.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/em28xx')
-rw-r--r-- | drivers/media/video/em28xx/em28xx-input.c | 21 |
1 files changed, 16 insertions, 5 deletions
diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index e2772a1470c..5c3fd9411b1 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c | |||
@@ -362,14 +362,20 @@ static void em28xx_ir_work(struct work_struct *work) | |||
362 | schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); | 362 | schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); |
363 | } | 363 | } |
364 | 364 | ||
365 | static void em28xx_ir_start(struct em28xx_IR *ir) | 365 | static int em28xx_ir_start(void *priv) |
366 | { | 366 | { |
367 | struct em28xx_IR *ir = priv; | ||
368 | |||
367 | INIT_DELAYED_WORK(&ir->work, em28xx_ir_work); | 369 | INIT_DELAYED_WORK(&ir->work, em28xx_ir_work); |
368 | schedule_delayed_work(&ir->work, 0); | 370 | schedule_delayed_work(&ir->work, 0); |
371 | |||
372 | return 0; | ||
369 | } | 373 | } |
370 | 374 | ||
371 | static void em28xx_ir_stop(struct em28xx_IR *ir) | 375 | static void em28xx_ir_stop(void *priv) |
372 | { | 376 | { |
377 | struct em28xx_IR *ir = priv; | ||
378 | |||
373 | cancel_delayed_work_sync(&ir->work); | 379 | cancel_delayed_work_sync(&ir->work); |
374 | } | 380 | } |
375 | 381 | ||
@@ -389,7 +395,7 @@ int em28xx_ir_change_protocol(void *priv, u64 ir_type) | |||
389 | dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE; | 395 | dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE; |
390 | ir_config = EM2874_IR_NEC; | 396 | ir_config = EM2874_IR_NEC; |
391 | ir->full_code = 1; | 397 | ir->full_code = 1; |
392 | } else | 398 | } else if (ir_type != IR_TYPE_UNKNOWN) |
393 | rc = -EINVAL; | 399 | rc = -EINVAL; |
394 | 400 | ||
395 | em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk, | 401 | em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk, |
@@ -442,6 +448,13 @@ int em28xx_ir_init(struct em28xx *dev) | |||
442 | ir->props.allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; | 448 | ir->props.allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; |
443 | ir->props.priv = ir; | 449 | ir->props.priv = ir; |
444 | ir->props.change_protocol = em28xx_ir_change_protocol; | 450 | ir->props.change_protocol = em28xx_ir_change_protocol; |
451 | ir->props.open = em28xx_ir_start; | ||
452 | ir->props.close = em28xx_ir_stop; | ||
453 | |||
454 | /* By default, keep protocol field untouched */ | ||
455 | err = em28xx_ir_change_protocol(ir, IR_TYPE_UNKNOWN); | ||
456 | if (err) | ||
457 | goto err_out_free; | ||
445 | 458 | ||
446 | /* This is how often we ask the chip for IR information */ | 459 | /* This is how often we ask the chip for IR information */ |
447 | ir->polling = 100; /* ms */ | 460 | ir->polling = 100; /* ms */ |
@@ -468,7 +481,6 @@ int em28xx_ir_init(struct em28xx *dev) | |||
468 | input_dev->dev.parent = &dev->udev->dev; | 481 | input_dev->dev.parent = &dev->udev->dev; |
469 | 482 | ||
470 | 483 | ||
471 | em28xx_ir_start(ir); | ||
472 | 484 | ||
473 | /* all done */ | 485 | /* all done */ |
474 | err = ir_input_register(ir->input, dev->board.ir_codes, | 486 | err = ir_input_register(ir->input, dev->board.ir_codes, |
@@ -478,7 +490,6 @@ int em28xx_ir_init(struct em28xx *dev) | |||
478 | 490 | ||
479 | return 0; | 491 | return 0; |
480 | err_out_stop: | 492 | err_out_stop: |
481 | em28xx_ir_stop(ir); | ||
482 | dev->ir = NULL; | 493 | dev->ir = NULL; |
483 | err_out_free: | 494 | err_out_free: |
484 | kfree(ir); | 495 | kfree(ir); |