diff options
Diffstat (limited to 'drivers/media/rc/img-ir')
-rw-r--r-- | drivers/media/rc/img-ir/Kconfig | 1 | ||||
-rw-r--r-- | drivers/media/rc/img-ir/img-ir-core.c | 1 | ||||
-rw-r--r-- | drivers/media/rc/img-ir/img-ir-hw.c | 28 | ||||
-rw-r--r-- | drivers/media/rc/img-ir/img-ir-hw.h | 6 |
4 files changed, 27 insertions, 9 deletions
diff --git a/drivers/media/rc/img-ir/Kconfig b/drivers/media/rc/img-ir/Kconfig index 03ba9fc170fb..580715c7fc5e 100644 --- a/drivers/media/rc/img-ir/Kconfig +++ b/drivers/media/rc/img-ir/Kconfig @@ -1,6 +1,7 @@ config IR_IMG tristate "ImgTec IR Decoder" depends on RC_CORE + depends on METAG || MIPS || COMPILE_TEST select IR_IMG_HW if !IR_IMG_RAW help Say Y or M here if you want to use the ImgTec infrared decoder diff --git a/drivers/media/rc/img-ir/img-ir-core.c b/drivers/media/rc/img-ir/img-ir-core.c index a0cac2f09109..77c78de4f5bf 100644 --- a/drivers/media/rc/img-ir/img-ir-core.c +++ b/drivers/media/rc/img-ir/img-ir-core.c @@ -166,7 +166,6 @@ MODULE_DEVICE_TABLE(of, img_ir_match); static struct platform_driver img_ir_driver = { .driver = { .name = "img-ir", - .owner = THIS_MODULE, .of_match_table = img_ir_match, .pm = &img_ir_pmops, }, diff --git a/drivers/media/rc/img-ir/img-ir-hw.c b/drivers/media/rc/img-ir/img-ir-hw.c index ec49f94425fc..2fd47c9bf5d8 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.c +++ b/drivers/media/rc/img-ir/img-ir-hw.c @@ -530,6 +530,22 @@ static void img_ir_set_decoder(struct img_ir_priv *priv, u32 ir_status, irq_en; spin_lock_irq(&priv->lock); + /* + * First record that the protocol is being stopped so that the end timer + * isn't restarted while we're trying to stop it. + */ + hw->stopping = true; + + /* + * Release the lock to stop the end timer, since the end timer handler + * acquires the lock and we don't want to deadlock waiting for it. + */ + spin_unlock_irq(&priv->lock); + del_timer_sync(&hw->end_timer); + spin_lock_irq(&priv->lock); + + hw->stopping = false; + /* switch off and disable interrupts */ img_ir_write(priv, IMG_IR_CONTROL, 0); irq_en = img_ir_read(priv, IMG_IR_IRQ_ENABLE); @@ -541,12 +557,13 @@ static void img_ir_set_decoder(struct img_ir_priv *priv, if (ir_status & (IMG_IR_RXDVAL | IMG_IR_RXDVALD2)) { ir_status &= ~(IMG_IR_RXDVAL | IMG_IR_RXDVALD2); img_ir_write(priv, IMG_IR_STATUS, ir_status); - img_ir_read(priv, IMG_IR_DATA_LW); - img_ir_read(priv, IMG_IR_DATA_UP); } - /* stop the end timer and switch back to normal mode */ - del_timer_sync(&hw->end_timer); + /* always read data to clear buffer if IR wakes the device */ + img_ir_read(priv, IMG_IR_DATA_LW); + img_ir_read(priv, IMG_IR_DATA_UP); + + /* switch back to normal mode */ hw->mode = IMG_IR_M_NORMAL; /* clear the wakeup scancode filter */ @@ -817,7 +834,8 @@ static void img_ir_handle_data(struct img_ir_priv *priv, u32 len, u64 raw) } - if (dec->repeat) { + /* we mustn't update the end timer while trying to stop it */ + if (dec->repeat && !hw->stopping) { unsigned long interval; img_ir_begin_repeat(priv); diff --git a/drivers/media/rc/img-ir/img-ir-hw.h b/drivers/media/rc/img-ir/img-ir-hw.h index 8fcc16c32c5b..5c2b216c5fe3 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.h +++ b/drivers/media/rc/img-ir/img-ir-hw.h @@ -186,9 +186,6 @@ struct img_ir_reg_timings { struct img_ir_timing_regvals rtimings; }; -int img_ir_register_decoder(struct img_ir_decoder *dec); -void img_ir_unregister_decoder(struct img_ir_decoder *dec); - struct img_ir_priv; #ifdef CONFIG_IR_IMG_HW @@ -214,6 +211,8 @@ enum img_ir_mode { * @flags: IMG_IR_F_*. * @filters: HW filters (derived from scancode filters). * @mode: Current decode mode. + * @stopping: Indicates that decoder is being taken down and timers + * should not be restarted. * @suspend_irqen: Saved IRQ enable mask over suspend. */ struct img_ir_priv_hw { @@ -229,6 +228,7 @@ struct img_ir_priv_hw { struct img_ir_filter filters[RC_FILTER_MAX]; enum img_ir_mode mode; + bool stopping; u32 suspend_irqen; }; |