#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
+#include <linux/timer.h>
#include <linux/of_graph.h>
#include <linux/videodev2.h>
#include <linux/workqueue.h>
#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 */
struct delayed_work delayed_work_enable_hotplug;
+ struct timer_list timer;
+ struct work_struct work_i2c_poll;
+
/* edid */
u8 edid_blocks_written;
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)
{
"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));
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:
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);