diff options
author | Hermann Pitton <hermann-pitton@arcor.de> | 2006-12-07 19:45:28 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2007-02-21 10:34:12 -0500 |
commit | 9160723ed620f31bf38332dee02041b1cb4c9967 (patch) | |
tree | 1e2bbbb78b98d9c21a769634f908874f79cbc7ba /drivers/media/video/saa7134/saa7134-input.c | |
parent | c8f71b01a50597e298dc3214a2f2be7b8d31170c (diff) |
V4L/DVB (4961): Add support for the ASUS P7131 remote control
Besides adding the board specific code, this patch moves
the RC5 decoding code from bt8xx to ir-functions.c to make it available
for all drivers.
Signed-off-by: Marc Fargas <telenieko.telenieko.com>
Signed-off-by: Hermann Pitton <hermann-pitton@arcor.de>
Signed-off-by: Hartmut Hackmann <hartmut.hackmann@t-online.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/saa7134/saa7134-input.c')
-rw-r--r-- | drivers/media/video/saa7134/saa7134-input.c | 86 |
1 files changed, 80 insertions, 6 deletions
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index e4252683a597..08848ebc682f 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c | |||
@@ -40,16 +40,24 @@ static int pinnacle_remote = 0; | |||
40 | module_param(pinnacle_remote, int, 0644); /* Choose Pinnacle PCTV remote */ | 40 | module_param(pinnacle_remote, int, 0644); /* Choose Pinnacle PCTV remote */ |
41 | MODULE_PARM_DESC(pinnacle_remote, "Specify Pinnacle PCTV remote: 0=coloured, 1=grey (defaults to 0)"); | 41 | MODULE_PARM_DESC(pinnacle_remote, "Specify Pinnacle PCTV remote: 0=coloured, 1=grey (defaults to 0)"); |
42 | 42 | ||
43 | int ir_rc5_remote_gap = 885; | ||
44 | module_param(ir_rc5_remote_gap, int, 0644); | ||
45 | int ir_rc5_key_timeout = 115; | ||
46 | module_param(ir_rc5_key_timeout, int, 0644); | ||
47 | |||
43 | #define dprintk(fmt, arg...) if (ir_debug) \ | 48 | #define dprintk(fmt, arg...) if (ir_debug) \ |
44 | printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg) | 49 | printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg) |
45 | #define i2cdprintk(fmt, arg...) if (ir_debug) \ | 50 | #define i2cdprintk(fmt, arg...) if (ir_debug) \ |
46 | printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg) | 51 | printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg) |
47 | 52 | ||
53 | /** rc5 functions */ | ||
54 | static int saa7134_rc5_irq(struct saa7134_dev *dev); | ||
55 | |||
48 | /* -------------------- GPIO generic keycode builder -------------------- */ | 56 | /* -------------------- GPIO generic keycode builder -------------------- */ |
49 | 57 | ||
50 | static int build_key(struct saa7134_dev *dev) | 58 | static int build_key(struct saa7134_dev *dev) |
51 | { | 59 | { |
52 | struct saa7134_ir *ir = dev->remote; | 60 | struct card_ir *ir = dev->remote; |
53 | u32 gpio, data; | 61 | u32 gpio, data; |
54 | 62 | ||
55 | /* rising SAA7134_GPIO_GPRESCAN reads the status */ | 63 | /* rising SAA7134_GPIO_GPRESCAN reads the status */ |
@@ -134,16 +142,19 @@ static int get_key_hvr1110(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | |||
134 | 142 | ||
135 | void saa7134_input_irq(struct saa7134_dev *dev) | 143 | void saa7134_input_irq(struct saa7134_dev *dev) |
136 | { | 144 | { |
137 | struct saa7134_ir *ir = dev->remote; | 145 | struct card_ir *ir = dev->remote; |
138 | 146 | ||
139 | if (!ir->polling) | 147 | if (!ir->polling && !ir->rc5_gpio) { |
140 | build_key(dev); | 148 | build_key(dev); |
149 | } else if (ir->rc5_gpio) { | ||
150 | saa7134_rc5_irq(dev); | ||
151 | } | ||
141 | } | 152 | } |
142 | 153 | ||
143 | static void saa7134_input_timer(unsigned long data) | 154 | static void saa7134_input_timer(unsigned long data) |
144 | { | 155 | { |
145 | struct saa7134_dev *dev = (struct saa7134_dev*)data; | 156 | struct saa7134_dev *dev = (struct saa7134_dev*)data; |
146 | struct saa7134_ir *ir = dev->remote; | 157 | struct card_ir *ir = dev->remote; |
147 | unsigned long timeout; | 158 | unsigned long timeout; |
148 | 159 | ||
149 | build_key(dev); | 160 | build_key(dev); |
@@ -151,7 +162,7 @@ static void saa7134_input_timer(unsigned long data) | |||
151 | mod_timer(&ir->timer, timeout); | 162 | mod_timer(&ir->timer, timeout); |
152 | } | 163 | } |
153 | 164 | ||
154 | static void saa7134_ir_start(struct saa7134_dev *dev, struct saa7134_ir *ir) | 165 | static void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir) |
155 | { | 166 | { |
156 | if (ir->polling) { | 167 | if (ir->polling) { |
157 | init_timer(&ir->timer); | 168 | init_timer(&ir->timer); |
@@ -159,6 +170,19 @@ static void saa7134_ir_start(struct saa7134_dev *dev, struct saa7134_ir *ir) | |||
159 | ir->timer.data = (unsigned long)dev; | 170 | ir->timer.data = (unsigned long)dev; |
160 | ir->timer.expires = jiffies + HZ; | 171 | ir->timer.expires = jiffies + HZ; |
161 | add_timer(&ir->timer); | 172 | add_timer(&ir->timer); |
173 | } else if (ir->rc5_gpio) { | ||
174 | /* set timer_end for code completion */ | ||
175 | init_timer(&ir->timer_end); | ||
176 | ir->timer_end.function = ir_rc5_timer_end; | ||
177 | ir->timer_end.data = (unsigned long)ir; | ||
178 | init_timer(&ir->timer_keyup); | ||
179 | ir->timer_keyup.function = ir_rc5_timer_keyup; | ||
180 | ir->timer_keyup.data = (unsigned long)ir; | ||
181 | ir->shift_by = 2; | ||
182 | ir->start = 0x2; | ||
183 | ir->addr = 0x17; | ||
184 | ir->rc5_key_timeout = ir_rc5_key_timeout; | ||
185 | ir->rc5_remote_gap = ir_rc5_remote_gap; | ||
162 | } | 186 | } |
163 | } | 187 | } |
164 | 188 | ||
@@ -170,13 +194,14 @@ static void saa7134_ir_stop(struct saa7134_dev *dev) | |||
170 | 194 | ||
171 | int saa7134_input_init1(struct saa7134_dev *dev) | 195 | int saa7134_input_init1(struct saa7134_dev *dev) |
172 | { | 196 | { |
173 | struct saa7134_ir *ir; | 197 | struct card_ir *ir; |
174 | struct input_dev *input_dev; | 198 | struct input_dev *input_dev; |
175 | IR_KEYTAB_TYPE *ir_codes = NULL; | 199 | IR_KEYTAB_TYPE *ir_codes = NULL; |
176 | u32 mask_keycode = 0; | 200 | u32 mask_keycode = 0; |
177 | u32 mask_keydown = 0; | 201 | u32 mask_keydown = 0; |
178 | u32 mask_keyup = 0; | 202 | u32 mask_keyup = 0; |
179 | int polling = 0; | 203 | int polling = 0; |
204 | int rc5_gpio = 0; | ||
180 | int ir_type = IR_TYPE_OTHER; | 205 | int ir_type = IR_TYPE_OTHER; |
181 | int err; | 206 | int err; |
182 | 207 | ||
@@ -295,6 +320,11 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
295 | mask_keycode = 0x0001F00; | 320 | mask_keycode = 0x0001F00; |
296 | mask_keydown = 0x0040000; | 321 | mask_keydown = 0x0040000; |
297 | break; | 322 | break; |
323 | case SAA7134_BOARD_ASUSTeK_P7131_DUAL: | ||
324 | ir_codes = ir_codes_asus_pc39; | ||
325 | mask_keydown = 0x0040000; | ||
326 | rc5_gpio = 1; | ||
327 | break; | ||
298 | } | 328 | } |
299 | if (NULL == ir_codes) { | 329 | if (NULL == ir_codes) { |
300 | printk("%s: Oops: IR config error [card=%d]\n", | 330 | printk("%s: Oops: IR config error [card=%d]\n", |
@@ -316,6 +346,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
316 | ir->mask_keydown = mask_keydown; | 346 | ir->mask_keydown = mask_keydown; |
317 | ir->mask_keyup = mask_keyup; | 347 | ir->mask_keyup = mask_keyup; |
318 | ir->polling = polling; | 348 | ir->polling = polling; |
349 | ir->rc5_gpio = rc5_gpio; | ||
319 | 350 | ||
320 | /* init input device */ | 351 | /* init input device */ |
321 | snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)", | 352 | snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)", |
@@ -402,6 +433,49 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir) | |||
402 | } | 433 | } |
403 | 434 | ||
404 | } | 435 | } |
436 | |||
437 | static int saa7134_rc5_irq(struct saa7134_dev *dev) | ||
438 | { | ||
439 | struct card_ir *ir = dev->remote; | ||
440 | struct timeval tv; | ||
441 | u32 gap; | ||
442 | unsigned long current_jiffies, timeout; | ||
443 | |||
444 | /* get time of bit */ | ||
445 | current_jiffies = jiffies; | ||
446 | do_gettimeofday(&tv); | ||
447 | |||
448 | /* avoid overflow with gap >1s */ | ||
449 | if (tv.tv_sec - ir->base_time.tv_sec > 1) { | ||
450 | gap = 200000; | ||
451 | } else { | ||
452 | gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + | ||
453 | tv.tv_usec - ir->base_time.tv_usec; | ||
454 | } | ||
455 | |||
456 | /* active code => add bit */ | ||
457 | if (ir->active) { | ||
458 | /* only if in the code (otherwise spurious IRQ or timer | ||
459 | late) */ | ||
460 | if (ir->last_bit < 28) { | ||
461 | ir->last_bit = (gap - ir_rc5_remote_gap / 2) / | ||
462 | ir_rc5_remote_gap; | ||
463 | ir->code |= 1 << ir->last_bit; | ||
464 | } | ||
465 | /* starting new code */ | ||
466 | } else { | ||
467 | ir->active = 1; | ||
468 | ir->code = 0; | ||
469 | ir->base_time = tv; | ||
470 | ir->last_bit = 0; | ||
471 | |||
472 | timeout = current_jiffies + (500 + 30 * HZ) / 1000; | ||
473 | mod_timer(&ir->timer_end, timeout); | ||
474 | } | ||
475 | |||
476 | return 1; | ||
477 | } | ||
478 | |||
405 | /* ---------------------------------------------------------------------- | 479 | /* ---------------------------------------------------------------------- |
406 | * Local variables: | 480 | * Local variables: |
407 | * c-basic-offset: 8 | 481 | * c-basic-offset: 8 |