1*cb7a01acSMauro Carvalho Chehab /* 2*cb7a01acSMauro Carvalho Chehab * 3*cb7a01acSMauro Carvalho Chehab * keyboard input driver for i2c IR remote controls 4*cb7a01acSMauro Carvalho Chehab * 5*cb7a01acSMauro Carvalho Chehab * Copyright (c) 2000-2003 Gerd Knorr <kraxel@bytesex.org> 6*cb7a01acSMauro Carvalho Chehab * modified for PixelView (BT878P+W/FM) by 7*cb7a01acSMauro Carvalho Chehab * Michal Kochanowicz <mkochano@pld.org.pl> 8*cb7a01acSMauro Carvalho Chehab * Christoph Bartelmus <lirc@bartelmus.de> 9*cb7a01acSMauro Carvalho Chehab * modified for KNC ONE TV Station/Anubis Typhoon TView Tuner by 10*cb7a01acSMauro Carvalho Chehab * Ulrich Mueller <ulrich.mueller42@web.de> 11*cb7a01acSMauro Carvalho Chehab * modified for em2820 based USB TV tuners by 12*cb7a01acSMauro Carvalho Chehab * Markus Rechberger <mrechberger@gmail.com> 13*cb7a01acSMauro Carvalho Chehab * modified for DViCO Fusion HDTV 5 RT GOLD by 14*cb7a01acSMauro Carvalho Chehab * Chaogui Zhang <czhang1974@gmail.com> 15*cb7a01acSMauro Carvalho Chehab * modified for MSI TV@nywhere Plus by 16*cb7a01acSMauro Carvalho Chehab * Henry Wong <henry@stuffedcow.net> 17*cb7a01acSMauro Carvalho Chehab * Mark Schultz <n9xmj@yahoo.com> 18*cb7a01acSMauro Carvalho Chehab * Brian Rogers <brian_rogers@comcast.net> 19*cb7a01acSMauro Carvalho Chehab * modified for AVerMedia Cardbus by 20*cb7a01acSMauro Carvalho Chehab * Oldrich Jedlicka <oldium.pro@seznam.cz> 21*cb7a01acSMauro Carvalho Chehab * 22*cb7a01acSMauro Carvalho Chehab * This program is free software; you can redistribute it and/or modify 23*cb7a01acSMauro Carvalho Chehab * it under the terms of the GNU General Public License as published by 24*cb7a01acSMauro Carvalho Chehab * the Free Software Foundation; either version 2 of the License, or 25*cb7a01acSMauro Carvalho Chehab * (at your option) any later version. 26*cb7a01acSMauro Carvalho Chehab * 27*cb7a01acSMauro Carvalho Chehab * This program is distributed in the hope that it will be useful, 28*cb7a01acSMauro Carvalho Chehab * but WITHOUT ANY WARRANTY; without even the implied warranty of 29*cb7a01acSMauro Carvalho Chehab * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 30*cb7a01acSMauro Carvalho Chehab * GNU General Public License for more details. 31*cb7a01acSMauro Carvalho Chehab * 32*cb7a01acSMauro Carvalho Chehab * You should have received a copy of the GNU General Public License 33*cb7a01acSMauro Carvalho Chehab * along with this program; if not, write to the Free Software 34*cb7a01acSMauro Carvalho Chehab * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 35*cb7a01acSMauro Carvalho Chehab * 36*cb7a01acSMauro Carvalho Chehab */ 37*cb7a01acSMauro Carvalho Chehab 38*cb7a01acSMauro Carvalho Chehab #include <linux/module.h> 39*cb7a01acSMauro Carvalho Chehab #include <linux/init.h> 40*cb7a01acSMauro Carvalho Chehab #include <linux/kernel.h> 41*cb7a01acSMauro Carvalho Chehab #include <linux/string.h> 42*cb7a01acSMauro Carvalho Chehab #include <linux/timer.h> 43*cb7a01acSMauro Carvalho Chehab #include <linux/delay.h> 44*cb7a01acSMauro Carvalho Chehab #include <linux/errno.h> 45*cb7a01acSMauro Carvalho Chehab #include <linux/slab.h> 46*cb7a01acSMauro Carvalho Chehab #include <linux/i2c.h> 47*cb7a01acSMauro Carvalho Chehab #include <linux/workqueue.h> 48*cb7a01acSMauro Carvalho Chehab 49*cb7a01acSMauro Carvalho Chehab #include <media/rc-core.h> 50*cb7a01acSMauro Carvalho Chehab #include <media/ir-kbd-i2c.h> 51*cb7a01acSMauro Carvalho Chehab 52*cb7a01acSMauro Carvalho Chehab /* ----------------------------------------------------------------------- */ 53*cb7a01acSMauro Carvalho Chehab /* insmod parameters */ 54*cb7a01acSMauro Carvalho Chehab 55*cb7a01acSMauro Carvalho Chehab static int debug; 56*cb7a01acSMauro Carvalho Chehab module_param(debug, int, 0644); /* debug level (0,1,2) */ 57*cb7a01acSMauro Carvalho Chehab 58*cb7a01acSMauro Carvalho Chehab 59*cb7a01acSMauro Carvalho Chehab #define MODULE_NAME "ir-kbd-i2c" 60*cb7a01acSMauro Carvalho Chehab #define dprintk(level, fmt, arg...) if (debug >= level) \ 61*cb7a01acSMauro Carvalho Chehab printk(KERN_DEBUG MODULE_NAME ": " fmt , ## arg) 62*cb7a01acSMauro Carvalho Chehab 63*cb7a01acSMauro Carvalho Chehab /* ----------------------------------------------------------------------- */ 64*cb7a01acSMauro Carvalho Chehab 65*cb7a01acSMauro Carvalho Chehab static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw, 66*cb7a01acSMauro Carvalho Chehab int size, int offset) 67*cb7a01acSMauro Carvalho Chehab { 68*cb7a01acSMauro Carvalho Chehab unsigned char buf[6]; 69*cb7a01acSMauro Carvalho Chehab int start, range, toggle, dev, code, ircode; 70*cb7a01acSMauro Carvalho Chehab 71*cb7a01acSMauro Carvalho Chehab /* poll IR chip */ 72*cb7a01acSMauro Carvalho Chehab if (size != i2c_master_recv(ir->c, buf, size)) 73*cb7a01acSMauro Carvalho Chehab return -EIO; 74*cb7a01acSMauro Carvalho Chehab 75*cb7a01acSMauro Carvalho Chehab /* split rc5 data block ... */ 76*cb7a01acSMauro Carvalho Chehab start = (buf[offset] >> 7) & 1; 77*cb7a01acSMauro Carvalho Chehab range = (buf[offset] >> 6) & 1; 78*cb7a01acSMauro Carvalho Chehab toggle = (buf[offset] >> 5) & 1; 79*cb7a01acSMauro Carvalho Chehab dev = buf[offset] & 0x1f; 80*cb7a01acSMauro Carvalho Chehab code = (buf[offset+1] >> 2) & 0x3f; 81*cb7a01acSMauro Carvalho Chehab 82*cb7a01acSMauro Carvalho Chehab /* rc5 has two start bits 83*cb7a01acSMauro Carvalho Chehab * the first bit must be one 84*cb7a01acSMauro Carvalho Chehab * the second bit defines the command range (1 = 0-63, 0 = 64 - 127) 85*cb7a01acSMauro Carvalho Chehab */ 86*cb7a01acSMauro Carvalho Chehab if (!start) 87*cb7a01acSMauro Carvalho Chehab /* no key pressed */ 88*cb7a01acSMauro Carvalho Chehab return 0; 89*cb7a01acSMauro Carvalho Chehab /* 90*cb7a01acSMauro Carvalho Chehab * Hauppauge remotes (black/silver) always use 91*cb7a01acSMauro Carvalho Chehab * specific device ids. If we do not filter the 92*cb7a01acSMauro Carvalho Chehab * device ids then messages destined for devices 93*cb7a01acSMauro Carvalho Chehab * such as TVs (id=0) will get through causing 94*cb7a01acSMauro Carvalho Chehab * mis-fired events. 95*cb7a01acSMauro Carvalho Chehab * 96*cb7a01acSMauro Carvalho Chehab * We also filter out invalid key presses which 97*cb7a01acSMauro Carvalho Chehab * produce annoying debug log entries. 98*cb7a01acSMauro Carvalho Chehab */ 99*cb7a01acSMauro Carvalho Chehab ircode= (start << 12) | (toggle << 11) | (dev << 6) | code; 100*cb7a01acSMauro Carvalho Chehab if ((ircode & 0x1fff)==0x1fff) 101*cb7a01acSMauro Carvalho Chehab /* invalid key press */ 102*cb7a01acSMauro Carvalho Chehab return 0; 103*cb7a01acSMauro Carvalho Chehab 104*cb7a01acSMauro Carvalho Chehab if (!range) 105*cb7a01acSMauro Carvalho Chehab code += 64; 106*cb7a01acSMauro Carvalho Chehab 107*cb7a01acSMauro Carvalho Chehab dprintk(1,"ir hauppauge (rc5): s%d r%d t%d dev=%d code=%d\n", 108*cb7a01acSMauro Carvalho Chehab start, range, toggle, dev, code); 109*cb7a01acSMauro Carvalho Chehab 110*cb7a01acSMauro Carvalho Chehab /* return key */ 111*cb7a01acSMauro Carvalho Chehab *ir_key = (dev << 8) | code; 112*cb7a01acSMauro Carvalho Chehab *ir_raw = ircode; 113*cb7a01acSMauro Carvalho Chehab return 1; 114*cb7a01acSMauro Carvalho Chehab } 115*cb7a01acSMauro Carvalho Chehab 116*cb7a01acSMauro Carvalho Chehab static int get_key_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) 117*cb7a01acSMauro Carvalho Chehab { 118*cb7a01acSMauro Carvalho Chehab return get_key_haup_common (ir, ir_key, ir_raw, 3, 0); 119*cb7a01acSMauro Carvalho Chehab } 120*cb7a01acSMauro Carvalho Chehab 121*cb7a01acSMauro Carvalho Chehab static int get_key_haup_xvr(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) 122*cb7a01acSMauro Carvalho Chehab { 123*cb7a01acSMauro Carvalho Chehab int ret; 124*cb7a01acSMauro Carvalho Chehab unsigned char buf[1] = { 0 }; 125*cb7a01acSMauro Carvalho Chehab 126*cb7a01acSMauro Carvalho Chehab /* 127*cb7a01acSMauro Carvalho Chehab * This is the same apparent "are you ready?" poll command observed 128*cb7a01acSMauro Carvalho Chehab * watching Windows driver traffic and implemented in lirc_zilog. With 129*cb7a01acSMauro Carvalho Chehab * this added, we get far saner remote behavior with z8 chips on usb 130*cb7a01acSMauro Carvalho Chehab * connected devices, even with the default polling interval of 100ms. 131*cb7a01acSMauro Carvalho Chehab */ 132*cb7a01acSMauro Carvalho Chehab ret = i2c_master_send(ir->c, buf, 1); 133*cb7a01acSMauro Carvalho Chehab if (ret != 1) 134*cb7a01acSMauro Carvalho Chehab return (ret < 0) ? ret : -EINVAL; 135*cb7a01acSMauro Carvalho Chehab 136*cb7a01acSMauro Carvalho Chehab return get_key_haup_common (ir, ir_key, ir_raw, 6, 3); 137*cb7a01acSMauro Carvalho Chehab } 138*cb7a01acSMauro Carvalho Chehab 139*cb7a01acSMauro Carvalho Chehab static int get_key_pixelview(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) 140*cb7a01acSMauro Carvalho Chehab { 141*cb7a01acSMauro Carvalho Chehab unsigned char b; 142*cb7a01acSMauro Carvalho Chehab 143*cb7a01acSMauro Carvalho Chehab /* poll IR chip */ 144*cb7a01acSMauro Carvalho Chehab if (1 != i2c_master_recv(ir->c, &b, 1)) { 145*cb7a01acSMauro Carvalho Chehab dprintk(1,"read error\n"); 146*cb7a01acSMauro Carvalho Chehab return -EIO; 147*cb7a01acSMauro Carvalho Chehab } 148*cb7a01acSMauro Carvalho Chehab *ir_key = b; 149*cb7a01acSMauro Carvalho Chehab *ir_raw = b; 150*cb7a01acSMauro Carvalho Chehab return 1; 151*cb7a01acSMauro Carvalho Chehab } 152*cb7a01acSMauro Carvalho Chehab 153*cb7a01acSMauro Carvalho Chehab static int get_key_fusionhdtv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) 154*cb7a01acSMauro Carvalho Chehab { 155*cb7a01acSMauro Carvalho Chehab unsigned char buf[4]; 156*cb7a01acSMauro Carvalho Chehab 157*cb7a01acSMauro Carvalho Chehab /* poll IR chip */ 158*cb7a01acSMauro Carvalho Chehab if (4 != i2c_master_recv(ir->c, buf, 4)) { 159*cb7a01acSMauro Carvalho Chehab dprintk(1,"read error\n"); 160*cb7a01acSMauro Carvalho Chehab return -EIO; 161*cb7a01acSMauro Carvalho Chehab } 162*cb7a01acSMauro Carvalho Chehab 163*cb7a01acSMauro Carvalho Chehab if(buf[0] !=0 || buf[1] !=0 || buf[2] !=0 || buf[3] != 0) 164*cb7a01acSMauro Carvalho Chehab dprintk(2, "%s: 0x%2x 0x%2x 0x%2x 0x%2x\n", __func__, 165*cb7a01acSMauro Carvalho Chehab buf[0], buf[1], buf[2], buf[3]); 166*cb7a01acSMauro Carvalho Chehab 167*cb7a01acSMauro Carvalho Chehab /* no key pressed or signal from other ir remote */ 168*cb7a01acSMauro Carvalho Chehab if(buf[0] != 0x1 || buf[1] != 0xfe) 169*cb7a01acSMauro Carvalho Chehab return 0; 170*cb7a01acSMauro Carvalho Chehab 171*cb7a01acSMauro Carvalho Chehab *ir_key = buf[2]; 172*cb7a01acSMauro Carvalho Chehab *ir_raw = (buf[2] << 8) | buf[3]; 173*cb7a01acSMauro Carvalho Chehab 174*cb7a01acSMauro Carvalho Chehab return 1; 175*cb7a01acSMauro Carvalho Chehab } 176*cb7a01acSMauro Carvalho Chehab 177*cb7a01acSMauro Carvalho Chehab static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) 178*cb7a01acSMauro Carvalho Chehab { 179*cb7a01acSMauro Carvalho Chehab unsigned char b; 180*cb7a01acSMauro Carvalho Chehab 181*cb7a01acSMauro Carvalho Chehab /* poll IR chip */ 182*cb7a01acSMauro Carvalho Chehab if (1 != i2c_master_recv(ir->c, &b, 1)) { 183*cb7a01acSMauro Carvalho Chehab dprintk(1,"read error\n"); 184*cb7a01acSMauro Carvalho Chehab return -EIO; 185*cb7a01acSMauro Carvalho Chehab } 186*cb7a01acSMauro Carvalho Chehab 187*cb7a01acSMauro Carvalho Chehab /* it seems that 0xFE indicates that a button is still hold 188*cb7a01acSMauro Carvalho Chehab down, while 0xff indicates that no button is hold 189*cb7a01acSMauro Carvalho Chehab down. 0xfe sequences are sometimes interrupted by 0xFF */ 190*cb7a01acSMauro Carvalho Chehab 191*cb7a01acSMauro Carvalho Chehab dprintk(2,"key %02x\n", b); 192*cb7a01acSMauro Carvalho Chehab 193*cb7a01acSMauro Carvalho Chehab if (b == 0xff) 194*cb7a01acSMauro Carvalho Chehab return 0; 195*cb7a01acSMauro Carvalho Chehab 196*cb7a01acSMauro Carvalho Chehab if (b == 0xfe) 197*cb7a01acSMauro Carvalho Chehab /* keep old data */ 198*cb7a01acSMauro Carvalho Chehab return 1; 199*cb7a01acSMauro Carvalho Chehab 200*cb7a01acSMauro Carvalho Chehab *ir_key = b; 201*cb7a01acSMauro Carvalho Chehab *ir_raw = b; 202*cb7a01acSMauro Carvalho Chehab return 1; 203*cb7a01acSMauro Carvalho Chehab } 204*cb7a01acSMauro Carvalho Chehab 205*cb7a01acSMauro Carvalho Chehab static int get_key_avermedia_cardbus(struct IR_i2c *ir, 206*cb7a01acSMauro Carvalho Chehab u32 *ir_key, u32 *ir_raw) 207*cb7a01acSMauro Carvalho Chehab { 208*cb7a01acSMauro Carvalho Chehab unsigned char subaddr, key, keygroup; 209*cb7a01acSMauro Carvalho Chehab struct i2c_msg msg[] = { { .addr = ir->c->addr, .flags = 0, 210*cb7a01acSMauro Carvalho Chehab .buf = &subaddr, .len = 1}, 211*cb7a01acSMauro Carvalho Chehab { .addr = ir->c->addr, .flags = I2C_M_RD, 212*cb7a01acSMauro Carvalho Chehab .buf = &key, .len = 1} }; 213*cb7a01acSMauro Carvalho Chehab subaddr = 0x0d; 214*cb7a01acSMauro Carvalho Chehab if (2 != i2c_transfer(ir->c->adapter, msg, 2)) { 215*cb7a01acSMauro Carvalho Chehab dprintk(1, "read error\n"); 216*cb7a01acSMauro Carvalho Chehab return -EIO; 217*cb7a01acSMauro Carvalho Chehab } 218*cb7a01acSMauro Carvalho Chehab 219*cb7a01acSMauro Carvalho Chehab if (key == 0xff) 220*cb7a01acSMauro Carvalho Chehab return 0; 221*cb7a01acSMauro Carvalho Chehab 222*cb7a01acSMauro Carvalho Chehab subaddr = 0x0b; 223*cb7a01acSMauro Carvalho Chehab msg[1].buf = &keygroup; 224*cb7a01acSMauro Carvalho Chehab if (2 != i2c_transfer(ir->c->adapter, msg, 2)) { 225*cb7a01acSMauro Carvalho Chehab dprintk(1, "read error\n"); 226*cb7a01acSMauro Carvalho Chehab return -EIO; 227*cb7a01acSMauro Carvalho Chehab } 228*cb7a01acSMauro Carvalho Chehab 229*cb7a01acSMauro Carvalho Chehab if (keygroup == 0xff) 230*cb7a01acSMauro Carvalho Chehab return 0; 231*cb7a01acSMauro Carvalho Chehab 232*cb7a01acSMauro Carvalho Chehab dprintk(1, "read key 0x%02x/0x%02x\n", key, keygroup); 233*cb7a01acSMauro Carvalho Chehab if (keygroup < 2 || keygroup > 3) { 234*cb7a01acSMauro Carvalho Chehab /* Only a warning */ 235*cb7a01acSMauro Carvalho Chehab dprintk(1, "warning: invalid key group 0x%02x for key 0x%02x\n", 236*cb7a01acSMauro Carvalho Chehab keygroup, key); 237*cb7a01acSMauro Carvalho Chehab } 238*cb7a01acSMauro Carvalho Chehab key |= (keygroup & 1) << 6; 239*cb7a01acSMauro Carvalho Chehab 240*cb7a01acSMauro Carvalho Chehab *ir_key = key; 241*cb7a01acSMauro Carvalho Chehab *ir_raw = key; 242*cb7a01acSMauro Carvalho Chehab return 1; 243*cb7a01acSMauro Carvalho Chehab } 244*cb7a01acSMauro Carvalho Chehab 245*cb7a01acSMauro Carvalho Chehab /* ----------------------------------------------------------------------- */ 246*cb7a01acSMauro Carvalho Chehab 247*cb7a01acSMauro Carvalho Chehab static int ir_key_poll(struct IR_i2c *ir) 248*cb7a01acSMauro Carvalho Chehab { 249*cb7a01acSMauro Carvalho Chehab static u32 ir_key, ir_raw; 250*cb7a01acSMauro Carvalho Chehab int rc; 251*cb7a01acSMauro Carvalho Chehab 252*cb7a01acSMauro Carvalho Chehab dprintk(3, "%s\n", __func__); 253*cb7a01acSMauro Carvalho Chehab rc = ir->get_key(ir, &ir_key, &ir_raw); 254*cb7a01acSMauro Carvalho Chehab if (rc < 0) { 255*cb7a01acSMauro Carvalho Chehab dprintk(2,"error\n"); 256*cb7a01acSMauro Carvalho Chehab return rc; 257*cb7a01acSMauro Carvalho Chehab } 258*cb7a01acSMauro Carvalho Chehab 259*cb7a01acSMauro Carvalho Chehab if (rc) { 260*cb7a01acSMauro Carvalho Chehab dprintk(1, "%s: keycode = 0x%04x\n", __func__, ir_key); 261*cb7a01acSMauro Carvalho Chehab rc_keydown(ir->rc, ir_key, 0); 262*cb7a01acSMauro Carvalho Chehab } 263*cb7a01acSMauro Carvalho Chehab return 0; 264*cb7a01acSMauro Carvalho Chehab } 265*cb7a01acSMauro Carvalho Chehab 266*cb7a01acSMauro Carvalho Chehab static void ir_work(struct work_struct *work) 267*cb7a01acSMauro Carvalho Chehab { 268*cb7a01acSMauro Carvalho Chehab int rc; 269*cb7a01acSMauro Carvalho Chehab struct IR_i2c *ir = container_of(work, struct IR_i2c, work.work); 270*cb7a01acSMauro Carvalho Chehab 271*cb7a01acSMauro Carvalho Chehab rc = ir_key_poll(ir); 272*cb7a01acSMauro Carvalho Chehab if (rc == -ENODEV) { 273*cb7a01acSMauro Carvalho Chehab rc_unregister_device(ir->rc); 274*cb7a01acSMauro Carvalho Chehab ir->rc = NULL; 275*cb7a01acSMauro Carvalho Chehab return; 276*cb7a01acSMauro Carvalho Chehab } 277*cb7a01acSMauro Carvalho Chehab 278*cb7a01acSMauro Carvalho Chehab schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling_interval)); 279*cb7a01acSMauro Carvalho Chehab } 280*cb7a01acSMauro Carvalho Chehab 281*cb7a01acSMauro Carvalho Chehab /* ----------------------------------------------------------------------- */ 282*cb7a01acSMauro Carvalho Chehab 283*cb7a01acSMauro Carvalho Chehab static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) 284*cb7a01acSMauro Carvalho Chehab { 285*cb7a01acSMauro Carvalho Chehab char *ir_codes = NULL; 286*cb7a01acSMauro Carvalho Chehab const char *name = NULL; 287*cb7a01acSMauro Carvalho Chehab u64 rc_type = RC_TYPE_UNKNOWN; 288*cb7a01acSMauro Carvalho Chehab struct IR_i2c *ir; 289*cb7a01acSMauro Carvalho Chehab struct rc_dev *rc = NULL; 290*cb7a01acSMauro Carvalho Chehab struct i2c_adapter *adap = client->adapter; 291*cb7a01acSMauro Carvalho Chehab unsigned short addr = client->addr; 292*cb7a01acSMauro Carvalho Chehab int err; 293*cb7a01acSMauro Carvalho Chehab 294*cb7a01acSMauro Carvalho Chehab ir = kzalloc(sizeof(struct IR_i2c), GFP_KERNEL); 295*cb7a01acSMauro Carvalho Chehab if (!ir) 296*cb7a01acSMauro Carvalho Chehab return -ENOMEM; 297*cb7a01acSMauro Carvalho Chehab 298*cb7a01acSMauro Carvalho Chehab ir->c = client; 299*cb7a01acSMauro Carvalho Chehab ir->polling_interval = DEFAULT_POLLING_INTERVAL; 300*cb7a01acSMauro Carvalho Chehab i2c_set_clientdata(client, ir); 301*cb7a01acSMauro Carvalho Chehab 302*cb7a01acSMauro Carvalho Chehab switch(addr) { 303*cb7a01acSMauro Carvalho Chehab case 0x64: 304*cb7a01acSMauro Carvalho Chehab name = "Pixelview"; 305*cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_pixelview; 306*cb7a01acSMauro Carvalho Chehab rc_type = RC_TYPE_OTHER; 307*cb7a01acSMauro Carvalho Chehab ir_codes = RC_MAP_EMPTY; 308*cb7a01acSMauro Carvalho Chehab break; 309*cb7a01acSMauro Carvalho Chehab case 0x18: 310*cb7a01acSMauro Carvalho Chehab case 0x1f: 311*cb7a01acSMauro Carvalho Chehab case 0x1a: 312*cb7a01acSMauro Carvalho Chehab name = "Hauppauge"; 313*cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_haup; 314*cb7a01acSMauro Carvalho Chehab rc_type = RC_TYPE_RC5; 315*cb7a01acSMauro Carvalho Chehab ir_codes = RC_MAP_HAUPPAUGE; 316*cb7a01acSMauro Carvalho Chehab break; 317*cb7a01acSMauro Carvalho Chehab case 0x30: 318*cb7a01acSMauro Carvalho Chehab name = "KNC One"; 319*cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_knc1; 320*cb7a01acSMauro Carvalho Chehab rc_type = RC_TYPE_OTHER; 321*cb7a01acSMauro Carvalho Chehab ir_codes = RC_MAP_EMPTY; 322*cb7a01acSMauro Carvalho Chehab break; 323*cb7a01acSMauro Carvalho Chehab case 0x6b: 324*cb7a01acSMauro Carvalho Chehab name = "FusionHDTV"; 325*cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_fusionhdtv; 326*cb7a01acSMauro Carvalho Chehab rc_type = RC_TYPE_RC5; 327*cb7a01acSMauro Carvalho Chehab ir_codes = RC_MAP_FUSIONHDTV_MCE; 328*cb7a01acSMauro Carvalho Chehab break; 329*cb7a01acSMauro Carvalho Chehab case 0x40: 330*cb7a01acSMauro Carvalho Chehab name = "AVerMedia Cardbus remote"; 331*cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_avermedia_cardbus; 332*cb7a01acSMauro Carvalho Chehab rc_type = RC_TYPE_OTHER; 333*cb7a01acSMauro Carvalho Chehab ir_codes = RC_MAP_AVERMEDIA_CARDBUS; 334*cb7a01acSMauro Carvalho Chehab break; 335*cb7a01acSMauro Carvalho Chehab case 0x71: 336*cb7a01acSMauro Carvalho Chehab name = "Hauppauge/Zilog Z8"; 337*cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_haup_xvr; 338*cb7a01acSMauro Carvalho Chehab rc_type = RC_TYPE_RC5; 339*cb7a01acSMauro Carvalho Chehab ir_codes = RC_MAP_HAUPPAUGE; 340*cb7a01acSMauro Carvalho Chehab break; 341*cb7a01acSMauro Carvalho Chehab } 342*cb7a01acSMauro Carvalho Chehab 343*cb7a01acSMauro Carvalho Chehab /* Let the caller override settings */ 344*cb7a01acSMauro Carvalho Chehab if (client->dev.platform_data) { 345*cb7a01acSMauro Carvalho Chehab const struct IR_i2c_init_data *init_data = 346*cb7a01acSMauro Carvalho Chehab client->dev.platform_data; 347*cb7a01acSMauro Carvalho Chehab 348*cb7a01acSMauro Carvalho Chehab ir_codes = init_data->ir_codes; 349*cb7a01acSMauro Carvalho Chehab rc = init_data->rc_dev; 350*cb7a01acSMauro Carvalho Chehab 351*cb7a01acSMauro Carvalho Chehab name = init_data->name; 352*cb7a01acSMauro Carvalho Chehab if (init_data->type) 353*cb7a01acSMauro Carvalho Chehab rc_type = init_data->type; 354*cb7a01acSMauro Carvalho Chehab 355*cb7a01acSMauro Carvalho Chehab if (init_data->polling_interval) 356*cb7a01acSMauro Carvalho Chehab ir->polling_interval = init_data->polling_interval; 357*cb7a01acSMauro Carvalho Chehab 358*cb7a01acSMauro Carvalho Chehab switch (init_data->internal_get_key_func) { 359*cb7a01acSMauro Carvalho Chehab case IR_KBD_GET_KEY_CUSTOM: 360*cb7a01acSMauro Carvalho Chehab /* The bridge driver provided us its own function */ 361*cb7a01acSMauro Carvalho Chehab ir->get_key = init_data->get_key; 362*cb7a01acSMauro Carvalho Chehab break; 363*cb7a01acSMauro Carvalho Chehab case IR_KBD_GET_KEY_PIXELVIEW: 364*cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_pixelview; 365*cb7a01acSMauro Carvalho Chehab break; 366*cb7a01acSMauro Carvalho Chehab case IR_KBD_GET_KEY_HAUP: 367*cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_haup; 368*cb7a01acSMauro Carvalho Chehab break; 369*cb7a01acSMauro Carvalho Chehab case IR_KBD_GET_KEY_KNC1: 370*cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_knc1; 371*cb7a01acSMauro Carvalho Chehab break; 372*cb7a01acSMauro Carvalho Chehab case IR_KBD_GET_KEY_FUSIONHDTV: 373*cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_fusionhdtv; 374*cb7a01acSMauro Carvalho Chehab break; 375*cb7a01acSMauro Carvalho Chehab case IR_KBD_GET_KEY_HAUP_XVR: 376*cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_haup_xvr; 377*cb7a01acSMauro Carvalho Chehab break; 378*cb7a01acSMauro Carvalho Chehab case IR_KBD_GET_KEY_AVERMEDIA_CARDBUS: 379*cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_avermedia_cardbus; 380*cb7a01acSMauro Carvalho Chehab break; 381*cb7a01acSMauro Carvalho Chehab } 382*cb7a01acSMauro Carvalho Chehab } 383*cb7a01acSMauro Carvalho Chehab 384*cb7a01acSMauro Carvalho Chehab if (!rc) { 385*cb7a01acSMauro Carvalho Chehab /* 386*cb7a01acSMauro Carvalho Chehab * If platform_data doesn't specify rc_dev, initilize it 387*cb7a01acSMauro Carvalho Chehab * internally 388*cb7a01acSMauro Carvalho Chehab */ 389*cb7a01acSMauro Carvalho Chehab rc = rc_allocate_device(); 390*cb7a01acSMauro Carvalho Chehab if (!rc) { 391*cb7a01acSMauro Carvalho Chehab err = -ENOMEM; 392*cb7a01acSMauro Carvalho Chehab goto err_out_free; 393*cb7a01acSMauro Carvalho Chehab } 394*cb7a01acSMauro Carvalho Chehab } 395*cb7a01acSMauro Carvalho Chehab ir->rc = rc; 396*cb7a01acSMauro Carvalho Chehab 397*cb7a01acSMauro Carvalho Chehab /* Make sure we are all setup before going on */ 398*cb7a01acSMauro Carvalho Chehab if (!name || !ir->get_key || !rc_type || !ir_codes) { 399*cb7a01acSMauro Carvalho Chehab dprintk(1, ": Unsupported device at address 0x%02x\n", 400*cb7a01acSMauro Carvalho Chehab addr); 401*cb7a01acSMauro Carvalho Chehab err = -ENODEV; 402*cb7a01acSMauro Carvalho Chehab goto err_out_free; 403*cb7a01acSMauro Carvalho Chehab } 404*cb7a01acSMauro Carvalho Chehab 405*cb7a01acSMauro Carvalho Chehab /* Sets name */ 406*cb7a01acSMauro Carvalho Chehab snprintf(ir->name, sizeof(ir->name), "i2c IR (%s)", name); 407*cb7a01acSMauro Carvalho Chehab ir->ir_codes = ir_codes; 408*cb7a01acSMauro Carvalho Chehab 409*cb7a01acSMauro Carvalho Chehab snprintf(ir->phys, sizeof(ir->phys), "%s/%s/ir0", 410*cb7a01acSMauro Carvalho Chehab dev_name(&adap->dev), 411*cb7a01acSMauro Carvalho Chehab dev_name(&client->dev)); 412*cb7a01acSMauro Carvalho Chehab 413*cb7a01acSMauro Carvalho Chehab /* 414*cb7a01acSMauro Carvalho Chehab * Initialize input_dev fields 415*cb7a01acSMauro Carvalho Chehab * It doesn't make sense to allow overriding them via platform_data 416*cb7a01acSMauro Carvalho Chehab */ 417*cb7a01acSMauro Carvalho Chehab rc->input_id.bustype = BUS_I2C; 418*cb7a01acSMauro Carvalho Chehab rc->input_phys = ir->phys; 419*cb7a01acSMauro Carvalho Chehab rc->input_name = ir->name; 420*cb7a01acSMauro Carvalho Chehab 421*cb7a01acSMauro Carvalho Chehab /* 422*cb7a01acSMauro Carvalho Chehab * Initialize the other fields of rc_dev 423*cb7a01acSMauro Carvalho Chehab */ 424*cb7a01acSMauro Carvalho Chehab rc->map_name = ir->ir_codes; 425*cb7a01acSMauro Carvalho Chehab rc->allowed_protos = rc_type; 426*cb7a01acSMauro Carvalho Chehab if (!rc->driver_name) 427*cb7a01acSMauro Carvalho Chehab rc->driver_name = MODULE_NAME; 428*cb7a01acSMauro Carvalho Chehab 429*cb7a01acSMauro Carvalho Chehab err = rc_register_device(rc); 430*cb7a01acSMauro Carvalho Chehab if (err) 431*cb7a01acSMauro Carvalho Chehab goto err_out_free; 432*cb7a01acSMauro Carvalho Chehab 433*cb7a01acSMauro Carvalho Chehab printk(MODULE_NAME ": %s detected at %s [%s]\n", 434*cb7a01acSMauro Carvalho Chehab ir->name, ir->phys, adap->name); 435*cb7a01acSMauro Carvalho Chehab 436*cb7a01acSMauro Carvalho Chehab /* start polling via eventd */ 437*cb7a01acSMauro Carvalho Chehab INIT_DELAYED_WORK(&ir->work, ir_work); 438*cb7a01acSMauro Carvalho Chehab schedule_delayed_work(&ir->work, 0); 439*cb7a01acSMauro Carvalho Chehab 440*cb7a01acSMauro Carvalho Chehab return 0; 441*cb7a01acSMauro Carvalho Chehab 442*cb7a01acSMauro Carvalho Chehab err_out_free: 443*cb7a01acSMauro Carvalho Chehab /* Only frees rc if it were allocated internally */ 444*cb7a01acSMauro Carvalho Chehab rc_free_device(rc); 445*cb7a01acSMauro Carvalho Chehab kfree(ir); 446*cb7a01acSMauro Carvalho Chehab return err; 447*cb7a01acSMauro Carvalho Chehab } 448*cb7a01acSMauro Carvalho Chehab 449*cb7a01acSMauro Carvalho Chehab static int ir_remove(struct i2c_client *client) 450*cb7a01acSMauro Carvalho Chehab { 451*cb7a01acSMauro Carvalho Chehab struct IR_i2c *ir = i2c_get_clientdata(client); 452*cb7a01acSMauro Carvalho Chehab 453*cb7a01acSMauro Carvalho Chehab /* kill outstanding polls */ 454*cb7a01acSMauro Carvalho Chehab cancel_delayed_work_sync(&ir->work); 455*cb7a01acSMauro Carvalho Chehab 456*cb7a01acSMauro Carvalho Chehab /* unregister device */ 457*cb7a01acSMauro Carvalho Chehab if (ir->rc) 458*cb7a01acSMauro Carvalho Chehab rc_unregister_device(ir->rc); 459*cb7a01acSMauro Carvalho Chehab 460*cb7a01acSMauro Carvalho Chehab /* free memory */ 461*cb7a01acSMauro Carvalho Chehab kfree(ir); 462*cb7a01acSMauro Carvalho Chehab return 0; 463*cb7a01acSMauro Carvalho Chehab } 464*cb7a01acSMauro Carvalho Chehab 465*cb7a01acSMauro Carvalho Chehab static const struct i2c_device_id ir_kbd_id[] = { 466*cb7a01acSMauro Carvalho Chehab /* Generic entry for any IR receiver */ 467*cb7a01acSMauro Carvalho Chehab { "ir_video", 0 }, 468*cb7a01acSMauro Carvalho Chehab /* IR device specific entries should be added here */ 469*cb7a01acSMauro Carvalho Chehab { "ir_rx_z8f0811_haup", 0 }, 470*cb7a01acSMauro Carvalho Chehab { "ir_rx_z8f0811_hdpvr", 0 }, 471*cb7a01acSMauro Carvalho Chehab { } 472*cb7a01acSMauro Carvalho Chehab }; 473*cb7a01acSMauro Carvalho Chehab 474*cb7a01acSMauro Carvalho Chehab static struct i2c_driver ir_kbd_driver = { 475*cb7a01acSMauro Carvalho Chehab .driver = { 476*cb7a01acSMauro Carvalho Chehab .name = "ir-kbd-i2c", 477*cb7a01acSMauro Carvalho Chehab }, 478*cb7a01acSMauro Carvalho Chehab .probe = ir_probe, 479*cb7a01acSMauro Carvalho Chehab .remove = ir_remove, 480*cb7a01acSMauro Carvalho Chehab .id_table = ir_kbd_id, 481*cb7a01acSMauro Carvalho Chehab }; 482*cb7a01acSMauro Carvalho Chehab 483*cb7a01acSMauro Carvalho Chehab module_i2c_driver(ir_kbd_driver); 484*cb7a01acSMauro Carvalho Chehab 485*cb7a01acSMauro Carvalho Chehab /* ----------------------------------------------------------------------- */ 486*cb7a01acSMauro Carvalho Chehab 487*cb7a01acSMauro Carvalho Chehab MODULE_AUTHOR("Gerd Knorr, Michal Kochanowicz, Christoph Bartelmus, Ulrich Mueller"); 488*cb7a01acSMauro Carvalho Chehab MODULE_DESCRIPTION("input driver for i2c IR remote controls"); 489*cb7a01acSMauro Carvalho Chehab MODULE_LICENSE("GPL"); 490