blob: 092c7da0f37a7a534351536cd2f57ee15b01a4ab [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>
Chaogui Zhangd54d6982007-08-24 01:02:32 -030013 * modified for DViCO Fusion HDTV 5 RT GOLD by
14 * Chaogui Zhang <czhang1974@gmail.com>
Brian Rogersba340b42008-10-13 08:37:06 -030015 * modified for MSI TV@nywhere Plus by
16 * Henry Wong <henry@stuffedcow.net>
17 * Mark Schultz <n9xmj@yahoo.com>
18 * Brian Rogers <brian_rogers@comcast.net>
Oldřich Jedličkacb3bf502009-02-12 03:43:11 -030019 * modified for AVerMedia Cardbus by
20 * Oldrich Jedlicka <oldium.pro@seznam.cz>
Linus Torvalds1da177e2005-04-16 15:20:36 -070021 *
22 * This program is free software; you can redistribute it and/or modify
23 * it under the terms of the GNU General Public License as published by
24 * the Free Software Foundation; either version 2 of the License, or
25 * (at your option) any later version.
26 *
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
35 *
36 */
37
38#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070039#include <linux/init.h>
40#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <linux/string.h>
42#include <linux/timer.h>
43#include <linux/delay.h>
44#include <linux/errno.h>
45#include <linux/slab.h>
46#include <linux/i2c.h>
Jan Frey39cf1e82007-06-25 14:34:06 -030047#include <linux/i2c-id.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070048#include <linux/workqueue.h>
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -080049
Linus Torvalds1da177e2005-04-16 15:20:36 -070050#include <media/ir-common.h>
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -080051#include <media/ir-kbd-i2c.h>
Markus Rechbergerc3658642005-11-08 21:37:21 -080052
Linus Torvalds1da177e2005-04-16 15:20:36 -070053/* ----------------------------------------------------------------------- */
54/* insmod parameters */
55
56static int debug;
57module_param(debug, int, 0644); /* debug level (0,1,2) */
58
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030059static int hauppauge;
J.O. Ahobf47e4e2006-01-23 09:34:06 -020060module_param(hauppauge, int, 0644); /* Choose Hauppauge remote */
61MODULE_PARM_DESC(hauppauge, "Specify Hauppauge remote: 0=black, 1=grey (defaults to 0)");
62
63
Linus Torvalds1da177e2005-04-16 15:20:36 -070064#define DEVNAME "ir-kbd-i2c"
65#define dprintk(level, fmt, arg...) if (debug >= level) \
66 printk(KERN_DEBUG DEVNAME ": " fmt , ## arg)
67
68/* ----------------------------------------------------------------------- */
69
Jan Frey39cf1e82007-06-25 14:34:06 -030070static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
71 int size, int offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -070072{
Jan Frey39cf1e82007-06-25 14:34:06 -030073 unsigned char buf[6];
Darron Broad34c08022008-09-22 00:54:59 -030074 int start, range, toggle, dev, code, ircode;
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
76 /* poll IR chip */
Jan Frey39cf1e82007-06-25 14:34:06 -030077 if (size != i2c_master_recv(&ir->c,buf,size))
Linus Torvalds1da177e2005-04-16 15:20:36 -070078 return -EIO;
79
80 /* split rc5 data block ... */
Jan Frey39cf1e82007-06-25 14:34:06 -030081 start = (buf[offset] >> 7) & 1;
82 range = (buf[offset] >> 6) & 1;
83 toggle = (buf[offset] >> 5) & 1;
84 dev = buf[offset] & 0x1f;
85 code = (buf[offset+1] >> 2) & 0x3f;
Linus Torvalds1da177e2005-04-16 15:20:36 -070086
David Hardemancc7093d2006-09-26 16:39:00 -030087 /* rc5 has two start bits
88 * the first bit must be one
89 * the second bit defines the command range (1 = 0-63, 0 = 64 - 127)
90 */
91 if (!start)
Linus Torvalds1da177e2005-04-16 15:20:36 -070092 /* no key pressed */
93 return 0;
Darron Broad34c08022008-09-22 00:54:59 -030094 /*
95 * Hauppauge remotes (black/silver) always use
96 * specific device ids. If we do not filter the
97 * device ids then messages destined for devices
98 * such as TVs (id=0) will get through causing
99 * mis-fired events.
100 *
101 * We also filter out invalid key presses which
102 * produce annoying debug log entries.
103 */
104 ircode= (start << 12) | (toggle << 11) | (dev << 6) | code;
105 if ((ircode & 0x1fff)==0x1fff)
106 /* invalid key press */
107 return 0;
108
109 if (dev!=0x1e && dev!=0x1f)
110 /* not a hauppauge remote */
111 return 0;
David Hardemancc7093d2006-09-26 16:39:00 -0300112
113 if (!range)
114 code += 64;
115
116 dprintk(1,"ir hauppauge (rc5): s%d r%d t%d dev=%d code=%d\n",
117 start, range, toggle, dev, code);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118
119 /* return key */
120 *ir_key = code;
Darron Broad34c08022008-09-22 00:54:59 -0300121 *ir_raw = ircode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122 return 1;
123}
124
Jan Frey39cf1e82007-06-25 14:34:06 -0300125static inline int get_key_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
126{
127 return get_key_haup_common (ir, ir_key, ir_raw, 3, 0);
128}
129
130static inline int get_key_haup_xvr(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
131{
132 return get_key_haup_common (ir, ir_key, ir_raw, 6, 3);
133}
134
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800135static int get_key_pixelview(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136{
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800137 unsigned char b;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138
139 /* poll IR chip */
140 if (1 != i2c_master_recv(&ir->c,&b,1)) {
141 dprintk(1,"read error\n");
142 return -EIO;
143 }
144 *ir_key = b;
145 *ir_raw = b;
146 return 1;
147}
148
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800149static int get_key_pv951(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150{
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800151 unsigned char b;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152
153 /* poll IR chip */
154 if (1 != i2c_master_recv(&ir->c,&b,1)) {
155 dprintk(1,"read error\n");
156 return -EIO;
157 }
158
159 /* ignore 0xaa */
160 if (b==0xaa)
161 return 0;
162 dprintk(2,"key %02x\n", b);
163
164 *ir_key = b;
165 *ir_raw = b;
166 return 1;
167}
168
Michael Krufky3c443582007-08-24 01:07:12 -0300169static int get_key_fusionhdtv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
Chaogui Zhangd54d6982007-08-24 01:02:32 -0300170{
171 unsigned char buf[4];
172
173 /* poll IR chip */
174 if (4 != i2c_master_recv(&ir->c,buf,4)) {
175 dprintk(1,"read error\n");
176 return -EIO;
177 }
178
179 if(buf[0] !=0 || buf[1] !=0 || buf[2] !=0 || buf[3] != 0)
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300180 dprintk(2, "%s: 0x%2x 0x%2x 0x%2x 0x%2x\n", __func__,
Chaogui Zhangd54d6982007-08-24 01:02:32 -0300181 buf[0], buf[1], buf[2], buf[3]);
182
183 /* no key pressed or signal from other ir remote */
184 if(buf[0] != 0x1 || buf[1] != 0xfe)
185 return 0;
186
187 *ir_key = buf[2];
188 *ir_raw = (buf[2] << 8) | buf[3];
189
190 return 1;
Chaogui Zhangd54d6982007-08-24 01:02:32 -0300191}
192
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800193static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194{
195 unsigned char b;
196
197 /* poll IR chip */
198 if (1 != i2c_master_recv(&ir->c,&b,1)) {
199 dprintk(1,"read error\n");
200 return -EIO;
201 }
202
203 /* it seems that 0xFE indicates that a button is still hold
Mauro Carvalho Chehab4f9c05a2005-11-08 21:37:36 -0800204 down, while 0xff indicates that no button is hold
205 down. 0xfe sequences are sometimes interrupted by 0xFF */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206
207 dprintk(2,"key %02x\n", b);
208
Mauro Carvalho Chehab4f9c05a2005-11-08 21:37:36 -0800209 if (b == 0xff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 return 0;
211
Mauro Carvalho Chehab4f9c05a2005-11-08 21:37:36 -0800212 if (b == 0xfe)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 /* keep old data */
214 return 1;
215
216 *ir_key = b;
217 *ir_raw = b;
218 return 1;
219}
220
Oldřich Jedličkacb3bf502009-02-12 03:43:11 -0300221static int get_key_avermedia_cardbus(struct IR_i2c *ir,
222 u32 *ir_key, u32 *ir_raw)
223{
224 unsigned char subaddr, key, keygroup;
225 struct i2c_msg msg[] = { { .addr = ir->c.addr, .flags = 0,
226 .buf = &subaddr, .len = 1},
227 { .addr = ir->c.addr, .flags = I2C_M_RD,
228 .buf = &key, .len = 1} };
229 subaddr = 0x0d;
230 if (2 != i2c_transfer(ir->c.adapter, msg, 2)) {
231 dprintk(1, "read error\n");
232 return -EIO;
233 }
234
235 if (key == 0xff)
236 return 0;
237
238 subaddr = 0x0b;
239 msg[1].buf = &keygroup;
240 if (2 != i2c_transfer(ir->c.adapter, msg, 2)) {
241 dprintk(1, "read error\n");
242 return -EIO;
243 }
244
245 if (keygroup == 0xff)
246 return 0;
247
248 dprintk(1, "read key 0x%02x/0x%02x\n", key, keygroup);
249 if (keygroup < 2 || keygroup > 3) {
250 /* Only a warning */
251 dprintk(1, "warning: invalid key group 0x%02x for key 0x%02x\n",
252 keygroup, key);
253 }
254 key |= (keygroup & 1) << 6;
255
256 *ir_key = key;
257 *ir_raw = key;
258 return 1;
259}
260
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261/* ----------------------------------------------------------------------- */
262
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800263static void ir_key_poll(struct IR_i2c *ir)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264{
265 static u32 ir_key, ir_raw;
266 int rc;
267
268 dprintk(2,"ir_poll_key\n");
269 rc = ir->get_key(ir, &ir_key, &ir_raw);
270 if (rc < 0) {
271 dprintk(2,"error\n");
272 return;
273 }
274
275 if (0 == rc) {
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500276 ir_input_nokey(ir->input, &ir->ir);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 } else {
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500278 ir_input_keydown(ir->input, &ir->ir, ir_key, ir_raw);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 }
280}
281
David Howellsc4028952006-11-22 14:57:56 +0000282static void ir_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283{
Jean Delvarec1089bd2009-03-07 07:43:43 -0300284 struct IR_i2c *ir = container_of(work, struct IR_i2c, work.work);
Brian Rogersba340b42008-10-13 08:37:06 -0300285 int polling_interval = 100;
286
287 /* MSI TV@nywhere Plus requires more frequent polling
288 otherwise it will miss some keypresses */
289 if (ir->c.adapter->id == I2C_HW_SAA7134 && ir->c.addr == 0x30)
290 polling_interval = 50;
Dmitry Torokhov8083c522007-05-21 11:51:11 -0300291
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 ir_key_poll(ir);
Jean Delvarec1089bd2009-03-07 07:43:43 -0300293 schedule_delayed_work(&ir->work, msecs_to_jiffies(polling_interval));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294}
295
296/* ----------------------------------------------------------------------- */
297
298static int ir_attach(struct i2c_adapter *adap, int addr,
299 unsigned short flags, int kind);
300static int ir_detach(struct i2c_client *client);
301static int ir_probe(struct i2c_adapter *adap);
302
303static struct i2c_driver driver = {
Laurent Riffard604f28e2005-11-26 20:43:39 +0100304 .driver = {
Mauro Carvalho Chehabcab462f2006-01-09 15:53:26 -0200305 .name = "ir-kbd-i2c",
Laurent Riffard604f28e2005-11-26 20:43:39 +0100306 },
Mauro Carvalho Chehabdd815402005-12-12 00:37:31 -0800307 .id = I2C_DRIVERID_INFRARED,
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800308 .attach_adapter = ir_probe,
309 .detach_client = ir_detach,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310};
311
312static struct i2c_client client_template =
313{
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800314 .name = "unset",
315 .driver = &driver
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316};
317
318static int ir_attach(struct i2c_adapter *adap, int addr,
319 unsigned short flags, int kind)
320{
321 IR_KEYTAB_TYPE *ir_codes = NULL;
322 char *name;
323 int ir_type;
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800324 struct IR_i2c *ir;
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500325 struct input_dev *input_dev;
Dmitry Torokhovb07b4782006-11-20 10:23:04 -0300326 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -0800328 ir = kzalloc(sizeof(struct IR_i2c),GFP_KERNEL);
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500329 input_dev = input_allocate_device();
330 if (!ir || !input_dev) {
Dmitry Torokhovb07b4782006-11-20 10:23:04 -0300331 err = -ENOMEM;
332 goto err_out_free;
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500333 }
334
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335 ir->c = client_template;
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500336 ir->input = input_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 ir->c.adapter = adap;
339 ir->c.addr = addr;
340
Mauro Carvalho Chehabd21838d2006-01-09 15:25:21 -0200341 i2c_set_clientdata(&ir->c, ir);
342
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 switch(addr) {
344 case 0x64:
345 name = "Pixelview";
346 ir->get_key = get_key_pixelview;
347 ir_type = IR_TYPE_OTHER;
348 ir_codes = ir_codes_empty;
349 break;
350 case 0x4b:
351 name = "PV951";
352 ir->get_key = get_key_pv951;
353 ir_type = IR_TYPE_OTHER;
354 ir_codes = ir_codes_pv951;
355 break;
356 case 0x18:
357 case 0x1a:
358 name = "Hauppauge";
359 ir->get_key = get_key_haup;
360 ir_type = IR_TYPE_RC5;
J.O. Ahobf47e4e2006-01-23 09:34:06 -0200361 if (hauppauge == 1) {
Ricardo Cerqueira4c0f6312006-01-23 09:42:06 -0200362 ir_codes = ir_codes_hauppauge_new;
J.O. Ahobf47e4e2006-01-23 09:34:06 -0200363 } else {
364 ir_codes = ir_codes_rc5_tv;
365 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 break;
367 case 0x30:
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800368 name = "KNC One";
369 ir->get_key = get_key_knc1;
370 ir_type = IR_TYPE_OTHER;
371 ir_codes = ir_codes_empty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 break;
Chaogui Zhangd54d6982007-08-24 01:02:32 -0300373 case 0x6b:
Michael Krufky3c443582007-08-24 01:07:12 -0300374 name = "FusionHDTV";
375 ir->get_key = get_key_fusionhdtv;
Chaogui Zhangd54d6982007-08-24 01:02:32 -0300376 ir_type = IR_TYPE_RC5;
Michael Krufky3c443582007-08-24 01:07:12 -0300377 ir_codes = ir_codes_fusionhdtv_mce;
Chaogui Zhangd54d6982007-08-24 01:02:32 -0300378 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 case 0x7a:
Ricardo Cerqueiraac9cd972005-11-08 21:37:56 -0800380 case 0x47:
Thomas Genty177aaaf2006-11-29 21:57:24 -0300381 case 0x71:
Andrey J. Melnikoff (TEMHOTA)e8018c92008-01-07 05:17:39 -0300382 case 0x2d:
Jan Frey39cf1e82007-06-25 14:34:06 -0300383 if (adap->id == I2C_HW_B_CX2388x) {
384 /* Handled by cx88-input */
385 name = "CX2388x remote";
386 ir_type = IR_TYPE_RC5;
387 ir->get_key = get_key_haup_xvr;
388 if (hauppauge == 1) {
389 ir_codes = ir_codes_hauppauge_new;
390 } else {
391 ir_codes = ir_codes_rc5_tv;
392 }
393 } else {
394 /* Handled by saa7134-input */
395 name = "SAA713x remote";
396 ir_type = IR_TYPE_OTHER;
397 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 break;
Oldřich Jedličkacb3bf502009-02-12 03:43:11 -0300399 case 0x40:
400 name = "AVerMedia Cardbus remote";
401 ir->get_key = get_key_avermedia_cardbus;
402 ir_type = IR_TYPE_OTHER;
403 ir_codes = ir_codes_avermedia_cardbus;
404 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 default:
406 /* shouldn't happen */
Dmitry Torokhovb07b4782006-11-20 10:23:04 -0300407 printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n", addr);
408 err = -ENODEV;
409 goto err_out_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 }
411
Ricardo Cerqueiraac9cd972005-11-08 21:37:56 -0800412 /* Sets name */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (%s)", name);
Dmitry Torokhovb07b4782006-11-20 10:23:04 -0300414 ir->ir_codes = ir_codes;
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800415
416 /* register i2c device
417 * At device register, IR codes may be changed to be
418 * board dependent.
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -0800419 */
Dmitry Torokhovb07b4782006-11-20 10:23:04 -0300420 err = i2c_attach_client(&ir->c);
421 if (err)
422 goto err_out_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423
Ricardo Cerqueiraac9cd972005-11-08 21:37:56 -0800424 /* If IR not supported or disabled, unregisters driver */
425 if (ir->get_key == NULL) {
Dmitry Torokhovb07b4782006-11-20 10:23:04 -0300426 err = -ENODEV;
427 goto err_out_detach;
Ricardo Cerqueiraac9cd972005-11-08 21:37:56 -0800428 }
429
Kay Sieversaf128a12008-10-30 00:51:46 -0300430 /* Phys addr can only be set after attaching (for ir->c.dev) */
Ricardo Cerqueiraac9cd972005-11-08 21:37:56 -0800431 snprintf(ir->phys, sizeof(ir->phys), "%s/%s/ir0",
Kay Sieversaf128a12008-10-30 00:51:46 -0300432 dev_name(&ir->c.adapter->dev),
433 dev_name(&ir->c.dev));
Ricardo Cerqueiraac9cd972005-11-08 21:37:56 -0800434
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 /* init + register input device */
Dmitry Torokhovb07b4782006-11-20 10:23:04 -0300436 ir_input_init(input_dev, &ir->ir, ir_type, ir->ir_codes);
Mauro Carvalho Chehabd21838d2006-01-09 15:25:21 -0200437 input_dev->id.bustype = BUS_I2C;
438 input_dev->name = ir->c.name;
439 input_dev->phys = ir->phys;
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500440
Dmitry Torokhovb07b4782006-11-20 10:23:04 -0300441 err = input_register_device(ir->input);
442 if (err)
443 goto err_out_detach;
444
Mauro Carvalho Chehabd21838d2006-01-09 15:25:21 -0200445 printk(DEVNAME ": %s detected at %s [%s]\n",
Dmitry Torokhovb07b4782006-11-20 10:23:04 -0300446 ir->input->name, ir->input->phys, adap->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447
448 /* start polling via eventd */
Jean Delvarec1089bd2009-03-07 07:43:43 -0300449 INIT_DELAYED_WORK(&ir->work, ir_work);
450 schedule_delayed_work(&ir->work, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451
452 return 0;
Dmitry Torokhovb07b4782006-11-20 10:23:04 -0300453
454 err_out_detach:
455 i2c_detach_client(&ir->c);
456 err_out_free:
457 input_free_device(input_dev);
458 kfree(ir);
459 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460}
461
462static int ir_detach(struct i2c_client *client)
463{
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800464 struct IR_i2c *ir = i2c_get_clientdata(client);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465
466 /* kill outstanding polls */
Jean Delvarec1089bd2009-03-07 07:43:43 -0300467 cancel_delayed_work_sync(&ir->work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468
469 /* unregister devices */
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500470 input_unregister_device(ir->input);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 i2c_detach_client(&ir->c);
472
473 /* free memory */
474 kfree(ir);
475 return 0;
476}
477
478static int ir_probe(struct i2c_adapter *adap)
479{
480
481 /* The external IR receiver is at i2c address 0x34 (0x35 for
482 reads). Future Hauppauge cards will have an internal
483 receiver at 0x30 (0x31 for reads). In theory, both can be
484 fitted, and Hauppauge suggest an external overrides an
485 internal.
486
487 That's why we probe 0x1a (~0x34) first. CB
488 */
489
490 static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1};
Andrey J. Melnikoff (TEMHOTA)e8018c92008-01-07 05:17:39 -0300491 static const int probe_saa7134[] = { 0x7a, 0x47, 0x71, 0x2d, -1 };
Mauro Carvalho Chehabb296fc62005-11-08 21:38:37 -0800492 static const int probe_em28XX[] = { 0x30, 0x47, -1 };
Chaogui Zhangd54d6982007-08-24 01:02:32 -0300493 static const int probe_cx88[] = { 0x18, 0x6b, 0x71, -1 };
Michael Krufky9bc37ca2007-09-08 15:17:13 -0300494 static const int probe_cx23885[] = { 0x6b, -1 };
Jean Delvared6f34d72008-04-22 14:45:47 -0300495 const int *probe;
Jean Delvare37c45df2008-04-25 20:42:45 -0300496 struct i2c_msg msg = {
497 .flags = I2C_M_RD,
498 .len = 0,
499 .buf = NULL,
500 };
Marcin Slusarza5885852008-04-22 14:45:33 -0300501 int i, rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502
503 switch (adap->id) {
Jean Delvarec7a46532005-08-11 23:41:56 +0200504 case I2C_HW_B_BT848:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 probe = probe_bttv;
506 break;
Hans Verkuil51dab142006-03-25 08:10:12 -0300507 case I2C_HW_B_CX2341X:
Hans Verkuilc097b042006-03-30 19:57:28 -0300508 probe = probe_bttv;
Hans Verkuil51dab142006-03-25 08:10:12 -0300509 break;
Jean Delvare1684a9842005-08-11 23:51:10 +0200510 case I2C_HW_SAA7134:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511 probe = probe_saa7134;
512 break;
Mauro Carvalho Chehabb296fc62005-11-08 21:38:37 -0800513 case I2C_HW_B_EM28XX:
514 probe = probe_em28XX;
Markus Rechbergerc3658642005-11-08 21:37:21 -0800515 break;
Jan Frey39cf1e82007-06-25 14:34:06 -0300516 case I2C_HW_B_CX2388x:
517 probe = probe_cx88;
Trent Piepho415a1972007-10-15 20:39:25 -0300518 break;
Michael Krufky9bc37ca2007-09-08 15:17:13 -0300519 case I2C_HW_B_CX23885:
520 probe = probe_cx23885;
Jan Frey39cf1e82007-06-25 14:34:06 -0300521 break;
Jean Delvared6f34d72008-04-22 14:45:47 -0300522 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 return 0;
Jean Delvared6f34d72008-04-22 14:45:47 -0300524 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800526 for (i = 0; -1 != probe[i]; i++) {
Jean Delvare37c45df2008-04-25 20:42:45 -0300527 msg.addr = probe[i];
528 rc = i2c_transfer(adap, &msg, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 dprintk(1,"probe 0x%02x @ %s: %s\n",
530 probe[i], adap->name,
Jean Delvare37c45df2008-04-25 20:42:45 -0300531 (1 == rc) ? "yes" : "no");
532 if (1 == rc) {
Marcin Slusarza5885852008-04-22 14:45:33 -0300533 ir_attach(adap, probe[i], 0, 0);
Brian Rogersba340b42008-10-13 08:37:06 -0300534 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 }
536 }
Brian Rogersba340b42008-10-13 08:37:06 -0300537
538 /* Special case for MSI TV@nywhere Plus remote */
539 if (adap->id == I2C_HW_SAA7134) {
540 u8 temp;
541
542 /* MSI TV@nywhere Plus controller doesn't seem to
543 respond to probes unless we read something from
544 an existing device. Weird... */
545
546 msg.addr = 0x50;
547 rc = i2c_transfer(adap, &msg, 1);
548 dprintk(1, "probe 0x%02x @ %s: %s\n",
549 msg.addr, adap->name,
550 (1 == rc) ? "yes" : "no");
551
552 /* Now do the probe. The controller does not respond
553 to 0-byte reads, so we use a 1-byte read instead. */
554 msg.addr = 0x30;
555 msg.len = 1;
556 msg.buf = &temp;
557 rc = i2c_transfer(adap, &msg, 1);
558 dprintk(1, "probe 0x%02x @ %s: %s\n",
559 msg.addr, adap->name,
560 (1 == rc) ? "yes" : "no");
561 if (1 == rc)
562 ir_attach(adap, msg.addr, 0, 0);
563 }
564
Oldřich Jedličkacb3bf502009-02-12 03:43:11 -0300565 /* Special case for AVerMedia Cardbus remote */
566 if (adap->id == I2C_HW_SAA7134) {
567 unsigned char subaddr, data;
568 struct i2c_msg msg[] = { { .addr = 0x40, .flags = 0,
569 .buf = &subaddr, .len = 1},
570 { .addr = 0x40, .flags = I2C_M_RD,
571 .buf = &data, .len = 1} };
572 subaddr = 0x0d;
573 rc = i2c_transfer(adap, msg, 2);
574 dprintk(1, "probe 0x%02x/0x%02x @ %s: %s\n",
575 msg[0].addr, subaddr, adap->name,
576 (2 == rc) ? "yes" : "no");
577 if (2 == rc)
578 ir_attach(adap, msg[0].addr, 0, 0);
579 }
580
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 return 0;
582}
583
584/* ----------------------------------------------------------------------- */
585
586MODULE_AUTHOR("Gerd Knorr, Michal Kochanowicz, Christoph Bartelmus, Ulrich Mueller");
587MODULE_DESCRIPTION("input driver for i2c IR remote controls");
588MODULE_LICENSE("GPL");
589
590static int __init ir_init(void)
591{
592 return i2c_add_driver(&driver);
593}
594
595static void __exit ir_fini(void)
596{
597 i2c_del_driver(&driver);
598}
599
600module_init(ir_init);
601module_exit(ir_fini);
602
603/*
604 * Overrides for Emacs so that we follow Linus's tabbing style.
605 * ---------------------------------------------------------------------------
606 * Local variables:
607 * c-basic-offset: 8
608 * End:
609 */