blob: 0085567a1421d3fb5c06b145b0c302ec96a05895 [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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <media/ir-common.h>
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -080044#include <media/ir-kbd-i2c.h>
Markus Rechbergerc3658642005-11-08 21:37:21 -080045
Linus Torvalds1da177e2005-04-16 15:20:36 -070046/* Mark Phalan <phalanm@o2.ie> */
47static IR_KEYTAB_TYPE ir_codes_pv951[IR_KEYTAB_SIZE] = {
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -080048 [ 0 ] = KEY_KP0,
49 [ 1 ] = KEY_KP1,
50 [ 2 ] = KEY_KP2,
51 [ 3 ] = KEY_KP3,
52 [ 4 ] = KEY_KP4,
53 [ 5 ] = KEY_KP5,
54 [ 6 ] = KEY_KP6,
55 [ 7 ] = KEY_KP7,
56 [ 8 ] = KEY_KP8,
57 [ 9 ] = KEY_KP9,
Linus Torvalds1da177e2005-04-16 15:20:36 -070058
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -080059 [ 18 ] = KEY_POWER,
60 [ 16 ] = KEY_MUTE,
61 [ 31 ] = KEY_VOLUMEDOWN,
62 [ 27 ] = KEY_VOLUMEUP,
63 [ 26 ] = KEY_CHANNELUP,
64 [ 30 ] = KEY_CHANNELDOWN,
65 [ 14 ] = KEY_PAGEUP,
66 [ 29 ] = KEY_PAGEDOWN,
67 [ 19 ] = KEY_SOUND,
Linus Torvalds1da177e2005-04-16 15:20:36 -070068
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -080069 [ 24 ] = KEY_KPPLUSMINUS, /* CH +/- */
70 [ 22 ] = KEY_SUBTITLE, /* CC */
71 [ 13 ] = KEY_TEXT, /* TTX */
72 [ 11 ] = KEY_TV, /* AIR/CBL */
73 [ 17 ] = KEY_PC, /* PC/TV */
74 [ 23 ] = KEY_OK, /* CH RTN */
75 [ 25 ] = KEY_MODE, /* FUNC */
76 [ 12 ] = KEY_SEARCH, /* AUTOSCAN */
Linus Torvalds1da177e2005-04-16 15:20:36 -070077
78 /* Not sure what to do with these ones! */
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -080079 [ 15 ] = KEY_SELECT, /* SOURCE */
80 [ 10 ] = KEY_KPPLUS, /* +100 */
81 [ 20 ] = KEY_KPEQUAL, /* SYNC */
82 [ 28 ] = KEY_MEDIA, /* PC/TV */
Linus Torvalds1da177e2005-04-16 15:20:36 -070083};
84
Linus Torvalds1da177e2005-04-16 15:20:36 -070085/* ----------------------------------------------------------------------- */
86/* insmod parameters */
87
88static int debug;
89module_param(debug, int, 0644); /* debug level (0,1,2) */
90
91#define DEVNAME "ir-kbd-i2c"
92#define dprintk(level, fmt, arg...) if (debug >= level) \
93 printk(KERN_DEBUG DEVNAME ": " fmt , ## arg)
94
95/* ----------------------------------------------------------------------- */
96
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -080097static int get_key_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
Linus Torvalds1da177e2005-04-16 15:20:36 -070098{
99 unsigned char buf[3];
100 int start, toggle, dev, code;
101
102 /* poll IR chip */
103 if (3 != i2c_master_recv(&ir->c,buf,3))
104 return -EIO;
105
106 /* split rc5 data block ... */
107 start = (buf[0] >> 6) & 3;
108 toggle = (buf[0] >> 5) & 1;
109 dev = buf[0] & 0x1f;
110 code = (buf[1] >> 2) & 0x3f;
111
112 if (3 != start)
113 /* no key pressed */
114 return 0;
115 dprintk(1,"ir hauppauge (rc5): s%d t%d dev=%d code=%d\n",
116 start, toggle, dev, code);
117
118 /* return key */
119 *ir_key = code;
120 *ir_raw = (start << 12) | (toggle << 11) | (dev << 6) | code;
121 return 1;
122}
123
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800124static int get_key_pixelview(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125{
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800126 unsigned char b;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127
128 /* poll IR chip */
129 if (1 != i2c_master_recv(&ir->c,&b,1)) {
130 dprintk(1,"read error\n");
131 return -EIO;
132 }
133 *ir_key = b;
134 *ir_raw = b;
135 return 1;
136}
137
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800138static int get_key_pv951(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139{
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800140 unsigned char b;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141
142 /* poll IR chip */
143 if (1 != i2c_master_recv(&ir->c,&b,1)) {
144 dprintk(1,"read error\n");
145 return -EIO;
146 }
147
148 /* ignore 0xaa */
149 if (b==0xaa)
150 return 0;
151 dprintk(2,"key %02x\n", b);
152
153 *ir_key = b;
154 *ir_raw = b;
155 return 1;
156}
157
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800158static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159{
160 unsigned char b;
161
162 /* poll IR chip */
163 if (1 != i2c_master_recv(&ir->c,&b,1)) {
164 dprintk(1,"read error\n");
165 return -EIO;
166 }
167
168 /* it seems that 0xFE indicates that a button is still hold
Mauro Carvalho Chehab4f9c05a2005-11-08 21:37:36 -0800169 down, while 0xff indicates that no button is hold
170 down. 0xfe sequences are sometimes interrupted by 0xFF */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171
172 dprintk(2,"key %02x\n", b);
173
Mauro Carvalho Chehab4f9c05a2005-11-08 21:37:36 -0800174 if (b == 0xff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 return 0;
176
Mauro Carvalho Chehab4f9c05a2005-11-08 21:37:36 -0800177 if (b == 0xfe)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178 /* keep old data */
179 return 1;
180
181 *ir_key = b;
182 *ir_raw = b;
183 return 1;
184}
185
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186/* ----------------------------------------------------------------------- */
187
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800188static void ir_key_poll(struct IR_i2c *ir)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189{
190 static u32 ir_key, ir_raw;
191 int rc;
192
193 dprintk(2,"ir_poll_key\n");
194 rc = ir->get_key(ir, &ir_key, &ir_raw);
195 if (rc < 0) {
196 dprintk(2,"error\n");
197 return;
198 }
199
200 if (0 == rc) {
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500201 ir_input_nokey(ir->input, &ir->ir);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 } else {
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500203 ir_input_keydown(ir->input, &ir->ir, ir_key, ir_raw);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204 }
205}
206
207static void ir_timer(unsigned long data)
208{
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800209 struct IR_i2c *ir = (struct IR_i2c*)data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 schedule_work(&ir->work);
211}
212
213static void ir_work(void *data)
214{
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800215 struct IR_i2c *ir = data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216 ir_key_poll(ir);
217 mod_timer(&ir->timer, jiffies+HZ/10);
218}
219
220/* ----------------------------------------------------------------------- */
221
222static int ir_attach(struct i2c_adapter *adap, int addr,
223 unsigned short flags, int kind);
224static int ir_detach(struct i2c_client *client);
225static int ir_probe(struct i2c_adapter *adap);
226
227static struct i2c_driver driver = {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800228 .name = "ir remote kbd driver",
229 .id = I2C_DRIVERID_EXP3, /* FIXME */
230 .flags = I2C_DF_NOTIFY,
231 .attach_adapter = ir_probe,
232 .detach_client = ir_detach,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233};
234
235static struct i2c_client client_template =
236{
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800237 .name = "unset",
238 .driver = &driver
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239};
240
241static int ir_attach(struct i2c_adapter *adap, int addr,
242 unsigned short flags, int kind)
243{
244 IR_KEYTAB_TYPE *ir_codes = NULL;
245 char *name;
246 int ir_type;
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800247 struct IR_i2c *ir;
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500248 struct input_dev *input_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800250 ir = kzalloc(sizeof(struct IR_i2c), GFP_KERNEL);
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500251 input_dev = input_allocate_device();
252 if (!ir || !input_dev) {
253 kfree(ir);
254 input_free_device(input_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 return -ENOMEM;
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500256 }
257
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 ir->c = client_template;
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500259 ir->input = input_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260
261 i2c_set_clientdata(&ir->c, ir);
262 ir->c.adapter = adap;
263 ir->c.addr = addr;
264
265 switch(addr) {
266 case 0x64:
267 name = "Pixelview";
268 ir->get_key = get_key_pixelview;
269 ir_type = IR_TYPE_OTHER;
270 ir_codes = ir_codes_empty;
271 break;
272 case 0x4b:
273 name = "PV951";
274 ir->get_key = get_key_pv951;
275 ir_type = IR_TYPE_OTHER;
276 ir_codes = ir_codes_pv951;
277 break;
278 case 0x18:
279 case 0x1a:
280 name = "Hauppauge";
281 ir->get_key = get_key_haup;
282 ir_type = IR_TYPE_RC5;
283 ir_codes = ir_codes_rc5_tv;
284 break;
285 case 0x30:
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800286 name = "KNC One";
287 ir->get_key = get_key_knc1;
288 ir_type = IR_TYPE_OTHER;
289 ir_codes = ir_codes_empty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 break;
291 case 0x7a:
Ricardo Cerqueiraac9cd972005-11-08 21:37:56 -0800292 case 0x47:
293 /* Handled by saa7134-input */
294 name = "SAA713x remote";
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800295 ir_type = IR_TYPE_OTHER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 break;
297 default:
298 /* shouldn't happen */
299 printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n",addr);
300 kfree(ir);
301 return -1;
302 }
303
Ricardo Cerqueiraac9cd972005-11-08 21:37:56 -0800304 /* Sets name */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305 snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (%s)", name);
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800306 ir->ir_codes=ir_codes;
307
308 /* register i2c device
309 * At device register, IR codes may be changed to be
310 * board dependent.
311 */
312 i2c_attach_client(&ir->c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313
Ricardo Cerqueiraac9cd972005-11-08 21:37:56 -0800314 /* If IR not supported or disabled, unregisters driver */
315 if (ir->get_key == NULL) {
316 i2c_detach_client(&ir->c);
317 kfree(ir);
318 return -1;
319 }
320
321 /* Phys addr can only be set after attaching (for ir->c.dev.bus_id) */
322 snprintf(ir->phys, sizeof(ir->phys), "%s/%s/ir0",
323 ir->c.adapter->dev.bus_id,
324 ir->c.dev.bus_id);
325
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 /* init + register input device */
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500327 ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
328 input_dev->id.bustype = BUS_I2C;
329 input_dev->name = ir->c.name;
330 input_dev->phys = ir->phys;
331
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800332 /* register event device */
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500333 input_register_device(ir->input);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334
335 /* start polling via eventd */
336 INIT_WORK(&ir->work, ir_work, ir);
337 init_timer(&ir->timer);
338 ir->timer.function = ir_timer;
339 ir->timer.data = (unsigned long)ir;
340 schedule_work(&ir->work);
341
342 return 0;
343}
344
345static int ir_detach(struct i2c_client *client)
346{
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800347 struct IR_i2c *ir = i2c_get_clientdata(client);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348
349 /* kill outstanding polls */
350 del_timer(&ir->timer);
351 flush_scheduled_work();
352
353 /* unregister devices */
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500354 input_unregister_device(ir->input);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 i2c_detach_client(&ir->c);
356
357 /* free memory */
358 kfree(ir);
359 return 0;
360}
361
362static int ir_probe(struct i2c_adapter *adap)
363{
364
365 /* The external IR receiver is at i2c address 0x34 (0x35 for
366 reads). Future Hauppauge cards will have an internal
367 receiver at 0x30 (0x31 for reads). In theory, both can be
368 fitted, and Hauppauge suggest an external overrides an
369 internal.
370
371 That's why we probe 0x1a (~0x34) first. CB
372 */
373
374 static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1};
Ricardo Cerqueirac2f6f9d2005-11-08 21:37:51 -0800375 static const int probe_saa7134[] = { 0x7a, 0x47, -1 };
Mauro Carvalho Chehabb296fc62005-11-08 21:38:37 -0800376 static const int probe_em28XX[] = { 0x30, 0x47, -1 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 const int *probe = NULL;
Mauro Carvalho Chehab4f9c05a2005-11-08 21:37:36 -0800378 struct i2c_client c;
379 unsigned char buf;
380 int i,rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381
382 switch (adap->id) {
Jean Delvarec7a46532005-08-11 23:41:56 +0200383 case I2C_HW_B_BT848:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 probe = probe_bttv;
385 break;
Jean Delvare1684a9842005-08-11 23:51:10 +0200386 case I2C_HW_SAA7134:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 probe = probe_saa7134;
388 break;
Mauro Carvalho Chehabb296fc62005-11-08 21:38:37 -0800389 case I2C_HW_B_EM28XX:
390 probe = probe_em28XX;
Markus Rechbergerc3658642005-11-08 21:37:21 -0800391 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 }
393 if (NULL == probe)
394 return 0;
395
396 memset(&c,0,sizeof(c));
397 c.adapter = adap;
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800398 for (i = 0; -1 != probe[i]; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 c.addr = probe[i];
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800400 rc = i2c_master_recv(&c,&buf,0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 dprintk(1,"probe 0x%02x @ %s: %s\n",
402 probe[i], adap->name,
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800403 (0 == rc) ? "yes" : "no");
404 if (0 == rc) {
405 ir_attach(adap,probe[i],0,0);
406 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 }
408 }
409 return 0;
410}
411
412/* ----------------------------------------------------------------------- */
413
414MODULE_AUTHOR("Gerd Knorr, Michal Kochanowicz, Christoph Bartelmus, Ulrich Mueller");
415MODULE_DESCRIPTION("input driver for i2c IR remote controls");
416MODULE_LICENSE("GPL");
417
418static int __init ir_init(void)
419{
420 return i2c_add_driver(&driver);
421}
422
423static void __exit ir_fini(void)
424{
425 i2c_del_driver(&driver);
426}
427
428module_init(ir_init);
429module_exit(ir_fini);
430
431/*
432 * Overrides for Emacs so that we follow Linus's tabbing style.
433 * ---------------------------------------------------------------------------
434 * Local variables:
435 * c-basic-offset: 8
436 * End:
437 */