diff options
author | Andrzej Hajda <andrzej.hajda@wp.pl> | 2009-07-02 10:50:35 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-09-12 11:18:58 -0400 |
commit | 3c1c48bbcf892e97c4e965b8528f4d735bf9a746 (patch) | |
tree | 6919aad67cf57b9cab564740c8a0bce82efe53c4 /drivers/media/video/cx88 | |
parent | ecfcfec80493097967aa40e3433d65a8ff65c86b (diff) |
V4L/DVB (12465): cx88: High resolution timer for Remote Controls
Patch solves problem of missed keystrokes on some remote controls,
as reported on http://bugzilla.kernel.org/show_bug.cgi?id=9637 .
Signed-off-by: Andrzej Hajda <andrzej.hajda@wp.pl>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/cx88')
-rw-r--r-- | drivers/media/video/cx88/cx88-input.c | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 0abc3210072b..79c4408a6171 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c | |||
@@ -23,7 +23,7 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
26 | #include <linux/delay.h> | 26 | #include <linux/hrtimer.h> |
27 | #include <linux/input.h> | 27 | #include <linux/input.h> |
28 | #include <linux/pci.h> | 28 | #include <linux/pci.h> |
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
@@ -48,7 +48,7 @@ struct cx88_IR { | |||
48 | 48 | ||
49 | /* poll external decoder */ | 49 | /* poll external decoder */ |
50 | int polling; | 50 | int polling; |
51 | struct delayed_work work; | 51 | struct hrtimer timer; |
52 | u32 gpio_addr; | 52 | u32 gpio_addr; |
53 | u32 last_gpio; | 53 | u32 last_gpio; |
54 | u32 mask_keycode; | 54 | u32 mask_keycode; |
@@ -144,19 +144,28 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) | |||
144 | } | 144 | } |
145 | } | 145 | } |
146 | 146 | ||
147 | static void cx88_ir_work(struct work_struct *work) | 147 | static enum hrtimer_restart cx88_ir_work(struct hrtimer *timer) |
148 | { | 148 | { |
149 | struct cx88_IR *ir = container_of(work, struct cx88_IR, work.work); | 149 | unsigned long missed; |
150 | struct cx88_IR *ir = container_of(timer, struct cx88_IR, timer); | ||
150 | 151 | ||
151 | cx88_ir_handle_key(ir); | 152 | cx88_ir_handle_key(ir); |
152 | schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); | 153 | missed = hrtimer_forward_now(&ir->timer, |
154 | ktime_set(0, ir->polling * 1000000)); | ||
155 | if (missed > 1) | ||
156 | ir_dprintk("Missed ticks %ld\n", missed - 1); | ||
157 | |||
158 | return HRTIMER_RESTART; | ||
153 | } | 159 | } |
154 | 160 | ||
155 | void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir) | 161 | void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir) |
156 | { | 162 | { |
157 | if (ir->polling) { | 163 | if (ir->polling) { |
158 | INIT_DELAYED_WORK(&ir->work, cx88_ir_work); | 164 | hrtimer_init(&ir->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); |
159 | schedule_delayed_work(&ir->work, 0); | 165 | ir->timer.function = cx88_ir_work; |
166 | hrtimer_start(&ir->timer, | ||
167 | ktime_set(0, ir->polling * 1000000), | ||
168 | HRTIMER_MODE_REL); | ||
160 | } | 169 | } |
161 | if (ir->sampling) { | 170 | if (ir->sampling) { |
162 | core->pci_irqmask |= PCI_INT_IR_SMPINT; | 171 | core->pci_irqmask |= PCI_INT_IR_SMPINT; |
@@ -173,7 +182,7 @@ void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir) | |||
173 | } | 182 | } |
174 | 183 | ||
175 | if (ir->polling) | 184 | if (ir->polling) |
176 | cancel_delayed_work_sync(&ir->work); | 185 | hrtimer_cancel(&ir->timer); |
177 | } | 186 | } |
178 | 187 | ||
179 | /* ---------------------------------------------------------------------- */ | 188 | /* ---------------------------------------------------------------------- */ |