diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c index 7d20cac9711c..8c54013984ed 100644 --- a/drivers/media/i2c/tc358743.c +++ b/drivers/media/i2c/tc358743.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -62,6 +63,8 @@ MODULE_LICENSE("GPL"); #define I2C_MAX_XFER_SIZE (EDID_BLOCK_SIZE + 2) +#define POLL_INTERVAL_MS 1000 + static const struct v4l2_dv_timings_cap tc358743_timings_cap = { .type = V4L2_DV_BT_656_1120, /* keep this initialization for compatibility with GCC < 4.4.6 */ @@ -92,6 +95,9 @@ struct tc358743_state { struct delayed_work delayed_work_enable_hotplug; + struct timer_list timer; + struct work_struct work_i2c_poll; + /* edid */ u8 edid_blocks_written; @@ -1320,6 +1326,24 @@ static irqreturn_t tc358743_irq_handler(int irq, void *dev_id) return handled ? IRQ_HANDLED : IRQ_NONE; } +static void tc358743_irq_poll_timer(unsigned long arg) +{ + struct tc358743_state *state = (struct tc358743_state *)arg; + + schedule_work(&state->work_i2c_poll); + + mod_timer(&state->timer, jiffies + msecs_to_jiffies(POLL_INTERVAL_MS)); +} + +static void tc358743_work_i2c_poll(struct work_struct *work) +{ + struct tc358743_state *state = container_of(work, + struct tc358743_state, work_i2c_poll); + bool handled; + + tc358743_isr(&state->sd, 0, &handled); +} + static int tc358743_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, struct v4l2_event_subscription *sub) { @@ -1938,6 +1962,14 @@ static int tc358743_probe(struct i2c_client *client, "tc358743", state); if (err) goto err_work_queues; + } else { + INIT_WORK(&state->work_i2c_poll, + tc358743_work_i2c_poll); + state->timer.data = (unsigned long)state; + state->timer.function = tc358743_irq_poll_timer; + state->timer.expires = jiffies + + msecs_to_jiffies(POLL_INTERVAL_MS); + add_timer(&state->timer); } tc358743_enable_interrupts(sd, tx_5v_power_present(sd)); @@ -1953,6 +1985,8 @@ static int tc358743_probe(struct i2c_client *client, return 0; err_work_queues: + if (!state->i2c_client->irq) + flush_work(&state->work_i2c_poll); cancel_delayed_work(&state->delayed_work_enable_hotplug); mutex_destroy(&state->confctl_mutex); err_hdl: @@ -1966,6 +2000,10 @@ static int tc358743_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); struct tc358743_state *state = to_state(sd); + if (!state->i2c_client->irq) { + del_timer_sync(&state->timer); + flush_work(&state->work_i2c_poll); + } cancel_delayed_work(&state->delayed_work_enable_hotplug); v4l2_async_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);