blob: 7e66d83fe0ce672f6fb4cc0b4b53e28246d5b186 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 *
3 * keyboard input driver for i2c IR remote controls
4 *
5 * Copyright (c) 2000-2003 Gerd Knorr <kraxel@bytesex.org>
6 * modified for PixelView (BT878P+W/FM) by
7 * Michal Kochanowicz <mkochano@pld.org.pl>
8 * Christoph Bartelmus <lirc@bartelmus.de>
9 * modified for KNC ONE TV Station/Anubis Typhoon TView Tuner by
10 * Ulrich Mueller <ulrich.mueller42@web.de>
Markus Rechbergerc3658642005-11-08 21:37:21 -080011 * modified for em2820 based USB TV tuners by
12 * Markus Rechberger <mrechberger@gmail.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -070013 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 *
28 */
29
30#include <linux/module.h>
31#include <linux/moduleparam.h>
32#include <linux/init.h>
33#include <linux/kernel.h>
34#include <linux/sched.h>
35#include <linux/string.h>
36#include <linux/timer.h>
37#include <linux/delay.h>
38#include <linux/errno.h>
39#include <linux/slab.h>
40#include <linux/i2c.h>
41#include <linux/workqueue.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include <asm/semaphore.h>
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -080043
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#include <media/ir-common.h>
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -080045#include <media/ir-kbd-i2c.h>
Markus Rechbergerc3658642005-11-08 21:37:21 -080046
Linus Torvalds1da177e2005-04-16 15:20:36 -070047/* ----------------------------------------------------------------------- */
48/* insmod parameters */
49
50static int debug;
51module_param(debug, int, 0644); /* debug level (0,1,2) */
52
J.O. Ahobf47e4e2006-01-23 09:34:06 -020053static int hauppauge = 0;
54module_param(hauppauge, int, 0644); /* Choose Hauppauge remote */
55MODULE_PARM_DESC(hauppauge, "Specify Hauppauge remote: 0=black, 1=grey (defaults to 0)");
56
57
Linus Torvalds1da177e2005-04-16 15:20:36 -070058#define DEVNAME "ir-kbd-i2c"
59#define dprintk(level, fmt, arg...) if (debug >= level) \
60 printk(KERN_DEBUG DEVNAME ": " fmt , ## arg)
61
62/* ----------------------------------------------------------------------- */
63
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -080064static int get_key_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
Linus Torvalds1da177e2005-04-16 15:20:36 -070065{
66 unsigned char buf[3];
67 int start, toggle, dev, code;
68
69 /* poll IR chip */
70 if (3 != i2c_master_recv(&ir->c,buf,3))
71 return -EIO;
72
73 /* split rc5 data block ... */
74 start = (buf[0] >> 6) & 3;
75 toggle = (buf[0] >> 5) & 1;
76 dev = buf[0] & 0x1f;
77 code = (buf[1] >> 2) & 0x3f;
78
79 if (3 != start)
80 /* no key pressed */
81 return 0;
82 dprintk(1,"ir hauppauge (rc5): s%d t%d dev=%d code=%d\n",
83 start, toggle, dev, code);
84
85 /* return key */
86 *ir_key = code;
87 *ir_raw = (start << 12) | (toggle << 11) | (dev << 6) | code;
88 return 1;
89}
90
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -080091static int get_key_pixelview(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
Linus Torvalds1da177e2005-04-16 15:20:36 -070092{
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -080093 unsigned char b;
Linus Torvalds1da177e2005-04-16 15:20:36 -070094
95 /* poll IR chip */
96 if (1 != i2c_master_recv(&ir->c,&b,1)) {
97 dprintk(1,"read error\n");
98 return -EIO;
99 }
100 *ir_key = b;
101 *ir_raw = b;
102 return 1;
103}
104
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800105static int get_key_pv951(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106{
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800107 unsigned char b;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108
109 /* poll IR chip */
110 if (1 != i2c_master_recv(&ir->c,&b,1)) {
111 dprintk(1,"read error\n");
112 return -EIO;
113 }
114
115 /* ignore 0xaa */
116 if (b==0xaa)
117 return 0;
118 dprintk(2,"key %02x\n", b);
119
120 *ir_key = b;
121 *ir_raw = b;
122 return 1;
123}
124
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800125static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126{
127 unsigned char b;
128
129 /* poll IR chip */
130 if (1 != i2c_master_recv(&ir->c,&b,1)) {
131 dprintk(1,"read error\n");
132 return -EIO;
133 }
134
135 /* it seems that 0xFE indicates that a button is still hold
Mauro Carvalho Chehab4f9c05a2005-11-08 21:37:36 -0800136 down, while 0xff indicates that no button is hold
137 down. 0xfe sequences are sometimes interrupted by 0xFF */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138
139 dprintk(2,"key %02x\n", b);
140
Mauro Carvalho Chehab4f9c05a2005-11-08 21:37:36 -0800141 if (b == 0xff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 return 0;
143
Mauro Carvalho Chehab4f9c05a2005-11-08 21:37:36 -0800144 if (b == 0xfe)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145 /* keep old data */
146 return 1;
147
148 *ir_key = b;
149 *ir_raw = b;
150 return 1;
151}
152
Ricardo Cerqueira80696952005-11-13 16:07:49 -0800153/* The new pinnacle PCTV remote (with the colored buttons)
154 *
155 * Ricardo Cerqueira <v4l@cerqueira.org>
156 */
157
158int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
159{
160 unsigned char b[4];
161 unsigned int start = 0,parity = 0,code = 0;
162
163 /* poll IR chip */
164 if (4 != i2c_master_recv(&ir->c,b,4)) {
165 dprintk(2,"read error\n");
166 return -EIO;
167 }
168
169 for (start = 0; start<4; start++) {
170 if (b[start] == 0x80) {
171 code=b[(start+3)%4];
172 parity=b[(start+2)%4];
173 }
174 }
175
176 /* Empty Request */
177 if (parity==0)
178 return 0;
179
180 /* Repeating... */
181 if (ir->old == parity)
182 return 0;
183
184
185 ir->old = parity;
186
187 /* Reduce code value to fit inside IR_KEYTAB_SIZE
188 *
189 * this is the only value that results in 42 unique
190 * codes < 128
191 */
192
193 code %= 0x88;
194
195 *ir_raw = code;
196 *ir_key = code;
197
198 dprintk(1,"Pinnacle PCTV key %02x\n", code);
199
200 return 1;
201}
202
203EXPORT_SYMBOL_GPL(get_key_pinnacle);
204
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205/* ----------------------------------------------------------------------- */
206
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800207static void ir_key_poll(struct IR_i2c *ir)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208{
209 static u32 ir_key, ir_raw;
210 int rc;
211
212 dprintk(2,"ir_poll_key\n");
213 rc = ir->get_key(ir, &ir_key, &ir_raw);
214 if (rc < 0) {
215 dprintk(2,"error\n");
216 return;
217 }
218
219 if (0 == rc) {
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500220 ir_input_nokey(ir->input, &ir->ir);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221 } else {
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500222 ir_input_keydown(ir->input, &ir->ir, ir_key, ir_raw);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223 }
224}
225
226static void ir_timer(unsigned long data)
227{
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800228 struct IR_i2c *ir = (struct IR_i2c*)data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229 schedule_work(&ir->work);
230}
231
232static void ir_work(void *data)
233{
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800234 struct IR_i2c *ir = data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 ir_key_poll(ir);
236 mod_timer(&ir->timer, jiffies+HZ/10);
237}
238
239/* ----------------------------------------------------------------------- */
240
241static int ir_attach(struct i2c_adapter *adap, int addr,
242 unsigned short flags, int kind);
243static int ir_detach(struct i2c_client *client);
244static int ir_probe(struct i2c_adapter *adap);
245
246static struct i2c_driver driver = {
Laurent Riffard604f28e2005-11-26 20:43:39 +0100247 .driver = {
Mauro Carvalho Chehabcab462f2006-01-09 15:53:26 -0200248 .name = "ir-kbd-i2c",
Laurent Riffard604f28e2005-11-26 20:43:39 +0100249 },
Mauro Carvalho Chehabdd815402005-12-12 00:37:31 -0800250 .id = I2C_DRIVERID_INFRARED,
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800251 .attach_adapter = ir_probe,
252 .detach_client = ir_detach,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253};
254
255static struct i2c_client client_template =
256{
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800257 .name = "unset",
258 .driver = &driver
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259};
260
261static int ir_attach(struct i2c_adapter *adap, int addr,
262 unsigned short flags, int kind)
263{
264 IR_KEYTAB_TYPE *ir_codes = NULL;
265 char *name;
266 int ir_type;
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800267 struct IR_i2c *ir;
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500268 struct input_dev *input_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -0800270 ir = kzalloc(sizeof(struct IR_i2c),GFP_KERNEL);
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500271 input_dev = input_allocate_device();
272 if (!ir || !input_dev) {
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500273 input_free_device(input_dev);
Mauro Carvalho Chehabd21838d2006-01-09 15:25:21 -0200274 kfree(ir);
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800275 return -ENOMEM;
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500276 }
Mauro Carvalho Chehabd21838d2006-01-09 15:25:21 -0200277 memset(ir,0,sizeof(*ir));
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500278
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 ir->c = client_template;
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500280 ir->input = input_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 ir->c.adapter = adap;
283 ir->c.addr = addr;
284
Mauro Carvalho Chehabd21838d2006-01-09 15:25:21 -0200285 i2c_set_clientdata(&ir->c, ir);
286
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 switch(addr) {
288 case 0x64:
289 name = "Pixelview";
290 ir->get_key = get_key_pixelview;
291 ir_type = IR_TYPE_OTHER;
292 ir_codes = ir_codes_empty;
293 break;
294 case 0x4b:
295 name = "PV951";
296 ir->get_key = get_key_pv951;
297 ir_type = IR_TYPE_OTHER;
298 ir_codes = ir_codes_pv951;
299 break;
300 case 0x18:
301 case 0x1a:
302 name = "Hauppauge";
303 ir->get_key = get_key_haup;
304 ir_type = IR_TYPE_RC5;
J.O. Ahobf47e4e2006-01-23 09:34:06 -0200305 if (hauppauge == 1) {
Ricardo Cerqueira4c0f6312006-01-23 09:42:06 -0200306 ir_codes = ir_codes_hauppauge_new;
J.O. Ahobf47e4e2006-01-23 09:34:06 -0200307 } else {
308 ir_codes = ir_codes_rc5_tv;
309 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 break;
311 case 0x30:
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800312 name = "KNC One";
313 ir->get_key = get_key_knc1;
314 ir_type = IR_TYPE_OTHER;
315 ir_codes = ir_codes_empty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316 break;
317 case 0x7a:
Ricardo Cerqueiraac9cd972005-11-08 21:37:56 -0800318 case 0x47:
319 /* Handled by saa7134-input */
320 name = "SAA713x remote";
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800321 ir_type = IR_TYPE_OTHER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 break;
323 default:
324 /* shouldn't happen */
325 printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n",addr);
326 kfree(ir);
327 return -1;
328 }
329
Ricardo Cerqueiraac9cd972005-11-08 21:37:56 -0800330 /* Sets name */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331 snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (%s)", name);
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800332 ir->ir_codes=ir_codes;
333
334 /* register i2c device
335 * At device register, IR codes may be changed to be
336 * board dependent.
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -0800337 */
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800338 i2c_attach_client(&ir->c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339
Ricardo Cerqueiraac9cd972005-11-08 21:37:56 -0800340 /* If IR not supported or disabled, unregisters driver */
341 if (ir->get_key == NULL) {
342 i2c_detach_client(&ir->c);
343 kfree(ir);
344 return -1;
345 }
346
347 /* Phys addr can only be set after attaching (for ir->c.dev.bus_id) */
348 snprintf(ir->phys, sizeof(ir->phys), "%s/%s/ir0",
349 ir->c.adapter->dev.bus_id,
350 ir->c.dev.bus_id);
351
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 /* init + register input device */
Mauro Carvalho Chehabd21838d2006-01-09 15:25:21 -0200353 ir_input_init(input_dev,&ir->ir,ir_type,ir->ir_codes);
354 input_dev->id.bustype = BUS_I2C;
355 input_dev->name = ir->c.name;
356 input_dev->phys = ir->phys;
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500357
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800358 /* register event device */
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500359 input_register_device(ir->input);
Mauro Carvalho Chehabd21838d2006-01-09 15:25:21 -0200360 printk(DEVNAME ": %s detected at %s [%s]\n",
361 ir->input->name,ir->input->phys,adap->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362
363 /* start polling via eventd */
364 INIT_WORK(&ir->work, ir_work, ir);
365 init_timer(&ir->timer);
366 ir->timer.function = ir_timer;
367 ir->timer.data = (unsigned long)ir;
368 schedule_work(&ir->work);
369
370 return 0;
371}
372
373static int ir_detach(struct i2c_client *client)
374{
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800375 struct IR_i2c *ir = i2c_get_clientdata(client);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376
377 /* kill outstanding polls */
378 del_timer(&ir->timer);
379 flush_scheduled_work();
380
381 /* unregister devices */
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500382 input_unregister_device(ir->input);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 i2c_detach_client(&ir->c);
384
385 /* free memory */
386 kfree(ir);
387 return 0;
388}
389
390static int ir_probe(struct i2c_adapter *adap)
391{
392
393 /* The external IR receiver is at i2c address 0x34 (0x35 for
394 reads). Future Hauppauge cards will have an internal
395 receiver at 0x30 (0x31 for reads). In theory, both can be
396 fitted, and Hauppauge suggest an external overrides an
397 internal.
398
399 That's why we probe 0x1a (~0x34) first. CB
400 */
401
402 static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1};
Ricardo Cerqueirac2f6f9d2005-11-08 21:37:51 -0800403 static const int probe_saa7134[] = { 0x7a, 0x47, -1 };
Mauro Carvalho Chehabb296fc62005-11-08 21:38:37 -0800404 static const int probe_em28XX[] = { 0x30, 0x47, -1 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 const int *probe = NULL;
Mauro Carvalho Chehab4f9c05a2005-11-08 21:37:36 -0800406 struct i2c_client c;
407 unsigned char buf;
408 int i,rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409
410 switch (adap->id) {
Jean Delvarec7a46532005-08-11 23:41:56 +0200411 case I2C_HW_B_BT848:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 probe = probe_bttv;
413 break;
Hans Verkuil51dab142006-03-25 08:10:12 -0300414 case I2C_HW_B_CX2341X:
Hans Verkuilc097b042006-03-30 19:57:28 -0300415 probe = probe_bttv;
Hans Verkuil51dab142006-03-25 08:10:12 -0300416 break;
Jean Delvare1684a9842005-08-11 23:51:10 +0200417 case I2C_HW_SAA7134:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 probe = probe_saa7134;
419 break;
Mauro Carvalho Chehabb296fc62005-11-08 21:38:37 -0800420 case I2C_HW_B_EM28XX:
421 probe = probe_em28XX;
Markus Rechbergerc3658642005-11-08 21:37:21 -0800422 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 }
424 if (NULL == probe)
425 return 0;
426
427 memset(&c,0,sizeof(c));
428 c.adapter = adap;
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800429 for (i = 0; -1 != probe[i]; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 c.addr = probe[i];
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800431 rc = i2c_master_recv(&c,&buf,0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 dprintk(1,"probe 0x%02x @ %s: %s\n",
433 probe[i], adap->name,
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800434 (0 == rc) ? "yes" : "no");
435 if (0 == rc) {
436 ir_attach(adap,probe[i],0,0);
437 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438 }
439 }
440 return 0;
441}
442
443/* ----------------------------------------------------------------------- */
444
445MODULE_AUTHOR("Gerd Knorr, Michal Kochanowicz, Christoph Bartelmus, Ulrich Mueller");
446MODULE_DESCRIPTION("input driver for i2c IR remote controls");
447MODULE_LICENSE("GPL");
448
449static int __init ir_init(void)
450{
451 return i2c_add_driver(&driver);
452}
453
454static void __exit ir_fini(void)
455{
456 i2c_del_driver(&driver);
457}
458
459module_init(ir_init);
460module_exit(ir_fini);
461
462/*
463 * Overrides for Emacs so that we follow Linus's tabbing style.
464 * ---------------------------------------------------------------------------
465 * Local variables:
466 * c-basic-offset: 8
467 * End:
468 */