1cb7a01acSMauro Carvalho Chehab /* 2cb7a01acSMauro Carvalho Chehab * 3cb7a01acSMauro Carvalho Chehab * keyboard input driver for i2c IR remote controls 4cb7a01acSMauro Carvalho Chehab * 5cb7a01acSMauro Carvalho Chehab * Copyright (c) 2000-2003 Gerd Knorr <kraxel@bytesex.org> 6cb7a01acSMauro Carvalho Chehab * modified for PixelView (BT878P+W/FM) by 7cb7a01acSMauro Carvalho Chehab * Michal Kochanowicz <mkochano@pld.org.pl> 8cb7a01acSMauro Carvalho Chehab * Christoph Bartelmus <lirc@bartelmus.de> 9cb7a01acSMauro Carvalho Chehab * modified for KNC ONE TV Station/Anubis Typhoon TView Tuner by 10cb7a01acSMauro Carvalho Chehab * Ulrich Mueller <ulrich.mueller42@web.de> 11cb7a01acSMauro Carvalho Chehab * modified for em2820 based USB TV tuners by 12cb7a01acSMauro Carvalho Chehab * Markus Rechberger <mrechberger@gmail.com> 13cb7a01acSMauro Carvalho Chehab * modified for DViCO Fusion HDTV 5 RT GOLD by 14cb7a01acSMauro Carvalho Chehab * Chaogui Zhang <czhang1974@gmail.com> 15cb7a01acSMauro Carvalho Chehab * modified for MSI TV@nywhere Plus by 16cb7a01acSMauro Carvalho Chehab * Henry Wong <henry@stuffedcow.net> 17cb7a01acSMauro Carvalho Chehab * Mark Schultz <n9xmj@yahoo.com> 18cb7a01acSMauro Carvalho Chehab * Brian Rogers <brian_rogers@comcast.net> 19cb7a01acSMauro Carvalho Chehab * modified for AVerMedia Cardbus by 20cb7a01acSMauro Carvalho Chehab * Oldrich Jedlicka <oldium.pro@seznam.cz> 21*acaa34bfSSean Young * Zilog Transmitter portions/ideas were derived from GPLv2+ sources: 22*acaa34bfSSean Young * - drivers/char/pctv_zilogir.[ch] from Hauppauge Broadway product 23*acaa34bfSSean Young * Copyright 2011 Hauppauge Computer works 24*acaa34bfSSean Young * - drivers/staging/media/lirc/lirc_zilog.c 25*acaa34bfSSean Young * Copyright (c) 2000 Gerd Knorr <kraxel@goldbach.in-berlin.de> 26*acaa34bfSSean Young * Michal Kochanowicz <mkochano@pld.org.pl> 27*acaa34bfSSean Young * Christoph Bartelmus <lirc@bartelmus.de> 28*acaa34bfSSean Young * Ulrich Mueller <ulrich.mueller42@web.de> 29*acaa34bfSSean Young * Stefan Jahn <stefan@lkcc.org> 30*acaa34bfSSean Young * Jerome Brock <jbrock@users.sourceforge.net> 31*acaa34bfSSean Young * Thomas Reitmayr (treitmayr@yahoo.com) 32*acaa34bfSSean Young * Mark Weaver <mark@npsl.co.uk> 33*acaa34bfSSean Young * Jarod Wilson <jarod@redhat.com> 34*acaa34bfSSean Young * Copyright (C) 2011 Andy Walls <awalls@md.metrocast.net> 35cb7a01acSMauro Carvalho Chehab * 36cb7a01acSMauro Carvalho Chehab * This program is free software; you can redistribute it and/or modify 37cb7a01acSMauro Carvalho Chehab * it under the terms of the GNU General Public License as published by 38cb7a01acSMauro Carvalho Chehab * the Free Software Foundation; either version 2 of the License, or 39cb7a01acSMauro Carvalho Chehab * (at your option) any later version. 40cb7a01acSMauro Carvalho Chehab * 41cb7a01acSMauro Carvalho Chehab * This program is distributed in the hope that it will be useful, 42cb7a01acSMauro Carvalho Chehab * but WITHOUT ANY WARRANTY; without even the implied warranty of 43cb7a01acSMauro Carvalho Chehab * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 44cb7a01acSMauro Carvalho Chehab * GNU General Public License for more details. 45cb7a01acSMauro Carvalho Chehab * 46cb7a01acSMauro Carvalho Chehab */ 47cb7a01acSMauro Carvalho Chehab 4800bb8207SSean Young #include <asm/unaligned.h> 49cb7a01acSMauro Carvalho Chehab #include <linux/module.h> 50cb7a01acSMauro Carvalho Chehab #include <linux/init.h> 51cb7a01acSMauro Carvalho Chehab #include <linux/kernel.h> 52cb7a01acSMauro Carvalho Chehab #include <linux/string.h> 53cb7a01acSMauro Carvalho Chehab #include <linux/timer.h> 54cb7a01acSMauro Carvalho Chehab #include <linux/delay.h> 55cb7a01acSMauro Carvalho Chehab #include <linux/errno.h> 56cb7a01acSMauro Carvalho Chehab #include <linux/slab.h> 57cb7a01acSMauro Carvalho Chehab #include <linux/i2c.h> 58cb7a01acSMauro Carvalho Chehab #include <linux/workqueue.h> 59cb7a01acSMauro Carvalho Chehab 60cb7a01acSMauro Carvalho Chehab #include <media/rc-core.h> 61b5dcee22SMauro Carvalho Chehab #include <media/i2c/ir-kbd-i2c.h> 62cb7a01acSMauro Carvalho Chehab 63*acaa34bfSSean Young #define FLAG_TX 1 64*acaa34bfSSean Young #define FLAG_HDPVR 2 65cb7a01acSMauro Carvalho Chehab 666d741bfeSSean Young static int get_key_haup_common(struct IR_i2c *ir, enum rc_proto *protocol, 6700bb8207SSean Young u32 *scancode, u8 *ptoggle, int size) 68cb7a01acSMauro Carvalho Chehab { 69cb7a01acSMauro Carvalho Chehab unsigned char buf[6]; 7000bb8207SSean Young int start, range, toggle, dev, code, ircode, vendor; 71cb7a01acSMauro Carvalho Chehab 72cb7a01acSMauro Carvalho Chehab /* poll IR chip */ 73cb7a01acSMauro Carvalho Chehab if (size != i2c_master_recv(ir->c, buf, size)) 74cb7a01acSMauro Carvalho Chehab return -EIO; 75cb7a01acSMauro Carvalho Chehab 7600bb8207SSean Young if (buf[0] & 0x80) { 7700bb8207SSean Young int offset = (size == 6) ? 3 : 0; 7800bb8207SSean Young 79cb7a01acSMauro Carvalho Chehab /* split rc5 data block ... */ 80cb7a01acSMauro Carvalho Chehab start = (buf[offset] >> 7) & 1; 81cb7a01acSMauro Carvalho Chehab range = (buf[offset] >> 6) & 1; 82cb7a01acSMauro Carvalho Chehab toggle = (buf[offset] >> 5) & 1; 83cb7a01acSMauro Carvalho Chehab dev = buf[offset] & 0x1f; 84cb7a01acSMauro Carvalho Chehab code = (buf[offset+1] >> 2) & 0x3f; 85cb7a01acSMauro Carvalho Chehab 86cb7a01acSMauro Carvalho Chehab /* rc5 has two start bits 87cb7a01acSMauro Carvalho Chehab * the first bit must be one 8800bb8207SSean Young * the second bit defines the command range: 8900bb8207SSean Young * 1 = 0-63, 0 = 64 - 127 90cb7a01acSMauro Carvalho Chehab */ 91cb7a01acSMauro Carvalho Chehab if (!start) 92cb7a01acSMauro Carvalho Chehab /* no key pressed */ 93cb7a01acSMauro Carvalho Chehab return 0; 944dd9bb91SDavid Härdeman 954dd9bb91SDavid Härdeman /* filter out invalid key presses */ 96cb7a01acSMauro Carvalho Chehab ircode = (start << 12) | (toggle << 11) | (dev << 6) | code; 97cb7a01acSMauro Carvalho Chehab if ((ircode & 0x1fff) == 0x1fff) 98cb7a01acSMauro Carvalho Chehab return 0; 99cb7a01acSMauro Carvalho Chehab 100cb7a01acSMauro Carvalho Chehab if (!range) 101cb7a01acSMauro Carvalho Chehab code += 64; 102cb7a01acSMauro Carvalho Chehab 10350a762b4SSean Young dev_dbg(&ir->rc->dev, 10450a762b4SSean Young "ir hauppauge (rc5): s%d r%d t%d dev=%d code=%d\n", 105cb7a01acSMauro Carvalho Chehab start, range, toggle, dev, code); 106cb7a01acSMauro Carvalho Chehab 1076d741bfeSSean Young *protocol = RC_PROTO_RC5; 1084dd9bb91SDavid Härdeman *scancode = RC_SCANCODE_RC5(dev, code); 1094dd9bb91SDavid Härdeman *ptoggle = toggle; 11000bb8207SSean Young 111cb7a01acSMauro Carvalho Chehab return 1; 11200bb8207SSean Young } else if (size == 6 && (buf[0] & 0x40)) { 11300bb8207SSean Young code = buf[4]; 11400bb8207SSean Young dev = buf[3]; 11500bb8207SSean Young vendor = get_unaligned_be16(buf + 1); 11600bb8207SSean Young 11700bb8207SSean Young if (vendor == 0x800f) { 11800bb8207SSean Young *ptoggle = (dev & 0x80) != 0; 1196d741bfeSSean Young *protocol = RC_PROTO_RC6_MCE; 12000bb8207SSean Young dev &= 0x7f; 12150a762b4SSean Young dev_dbg(&ir->rc->dev, 12250a762b4SSean Young "ir hauppauge (rc6-mce): t%d vendor=%d dev=%d code=%d\n", 1239cdbe14fSArnd Bergmann *ptoggle, vendor, dev, code); 12400bb8207SSean Young } else { 12500bb8207SSean Young *ptoggle = 0; 1266d741bfeSSean Young *protocol = RC_PROTO_RC6_6A_32; 12750a762b4SSean Young dev_dbg(&ir->rc->dev, 12850a762b4SSean Young "ir hauppauge (rc6-6a-32): vendor=%d dev=%d code=%d\n", 12900bb8207SSean Young vendor, dev, code); 13000bb8207SSean Young } 13100bb8207SSean Young 13200bb8207SSean Young *scancode = RC_SCANCODE_RC6_6A(vendor, dev, code); 13300bb8207SSean Young 13400bb8207SSean Young return 1; 13500bb8207SSean Young } 13600bb8207SSean Young 13700bb8207SSean Young return 0; 138cb7a01acSMauro Carvalho Chehab } 139cb7a01acSMauro Carvalho Chehab 1406d741bfeSSean Young static int get_key_haup(struct IR_i2c *ir, enum rc_proto *protocol, 1414dd9bb91SDavid Härdeman u32 *scancode, u8 *toggle) 142cb7a01acSMauro Carvalho Chehab { 14300bb8207SSean Young return get_key_haup_common(ir, protocol, scancode, toggle, 3); 144cb7a01acSMauro Carvalho Chehab } 145cb7a01acSMauro Carvalho Chehab 1466d741bfeSSean Young static int get_key_haup_xvr(struct IR_i2c *ir, enum rc_proto *protocol, 1474dd9bb91SDavid Härdeman u32 *scancode, u8 *toggle) 148cb7a01acSMauro Carvalho Chehab { 149cb7a01acSMauro Carvalho Chehab int ret; 150cb7a01acSMauro Carvalho Chehab unsigned char buf[1] = { 0 }; 151cb7a01acSMauro Carvalho Chehab 152cb7a01acSMauro Carvalho Chehab /* 153cb7a01acSMauro Carvalho Chehab * This is the same apparent "are you ready?" poll command observed 154cb7a01acSMauro Carvalho Chehab * watching Windows driver traffic and implemented in lirc_zilog. With 155cb7a01acSMauro Carvalho Chehab * this added, we get far saner remote behavior with z8 chips on usb 156cb7a01acSMauro Carvalho Chehab * connected devices, even with the default polling interval of 100ms. 157cb7a01acSMauro Carvalho Chehab */ 158cb7a01acSMauro Carvalho Chehab ret = i2c_master_send(ir->c, buf, 1); 159cb7a01acSMauro Carvalho Chehab if (ret != 1) 160cb7a01acSMauro Carvalho Chehab return (ret < 0) ? ret : -EINVAL; 161cb7a01acSMauro Carvalho Chehab 16200bb8207SSean Young return get_key_haup_common(ir, protocol, scancode, toggle, 6); 163cb7a01acSMauro Carvalho Chehab } 164cb7a01acSMauro Carvalho Chehab 1656d741bfeSSean Young static int get_key_pixelview(struct IR_i2c *ir, enum rc_proto *protocol, 1664dd9bb91SDavid Härdeman u32 *scancode, u8 *toggle) 167cb7a01acSMauro Carvalho Chehab { 168cb7a01acSMauro Carvalho Chehab unsigned char b; 169cb7a01acSMauro Carvalho Chehab 170cb7a01acSMauro Carvalho Chehab /* poll IR chip */ 171cb7a01acSMauro Carvalho Chehab if (1 != i2c_master_recv(ir->c, &b, 1)) { 17250a762b4SSean Young dev_dbg(&ir->rc->dev, "read error\n"); 173cb7a01acSMauro Carvalho Chehab return -EIO; 174cb7a01acSMauro Carvalho Chehab } 1754dd9bb91SDavid Härdeman 1766d741bfeSSean Young *protocol = RC_PROTO_OTHER; 1774dd9bb91SDavid Härdeman *scancode = b; 1784dd9bb91SDavid Härdeman *toggle = 0; 179cb7a01acSMauro Carvalho Chehab return 1; 180cb7a01acSMauro Carvalho Chehab } 181cb7a01acSMauro Carvalho Chehab 1826d741bfeSSean Young static int get_key_fusionhdtv(struct IR_i2c *ir, enum rc_proto *protocol, 1834dd9bb91SDavid Härdeman u32 *scancode, u8 *toggle) 184cb7a01acSMauro Carvalho Chehab { 185cb7a01acSMauro Carvalho Chehab unsigned char buf[4]; 186cb7a01acSMauro Carvalho Chehab 187cb7a01acSMauro Carvalho Chehab /* poll IR chip */ 188cb7a01acSMauro Carvalho Chehab if (4 != i2c_master_recv(ir->c, buf, 4)) { 18950a762b4SSean Young dev_dbg(&ir->rc->dev, "read error\n"); 190cb7a01acSMauro Carvalho Chehab return -EIO; 191cb7a01acSMauro Carvalho Chehab } 192cb7a01acSMauro Carvalho Chehab 193cb7a01acSMauro Carvalho Chehab if (buf[0] != 0 || buf[1] != 0 || buf[2] != 0 || buf[3] != 0) 19450a762b4SSean Young dev_dbg(&ir->rc->dev, "%s: %*ph\n", __func__, 4, buf); 195cb7a01acSMauro Carvalho Chehab 196cb7a01acSMauro Carvalho Chehab /* no key pressed or signal from other ir remote */ 197cb7a01acSMauro Carvalho Chehab if(buf[0] != 0x1 || buf[1] != 0xfe) 198cb7a01acSMauro Carvalho Chehab return 0; 199cb7a01acSMauro Carvalho Chehab 2006d741bfeSSean Young *protocol = RC_PROTO_UNKNOWN; 2014dd9bb91SDavid Härdeman *scancode = buf[2]; 2024dd9bb91SDavid Härdeman *toggle = 0; 203cb7a01acSMauro Carvalho Chehab return 1; 204cb7a01acSMauro Carvalho Chehab } 205cb7a01acSMauro Carvalho Chehab 2066d741bfeSSean Young static int get_key_knc1(struct IR_i2c *ir, enum rc_proto *protocol, 2074dd9bb91SDavid Härdeman u32 *scancode, u8 *toggle) 208cb7a01acSMauro Carvalho Chehab { 209cb7a01acSMauro Carvalho Chehab unsigned char b; 210cb7a01acSMauro Carvalho Chehab 211cb7a01acSMauro Carvalho Chehab /* poll IR chip */ 212cb7a01acSMauro Carvalho Chehab if (1 != i2c_master_recv(ir->c, &b, 1)) { 21350a762b4SSean Young dev_dbg(&ir->rc->dev, "read error\n"); 214cb7a01acSMauro Carvalho Chehab return -EIO; 215cb7a01acSMauro Carvalho Chehab } 216cb7a01acSMauro Carvalho Chehab 217cb7a01acSMauro Carvalho Chehab /* it seems that 0xFE indicates that a button is still hold 218cb7a01acSMauro Carvalho Chehab down, while 0xff indicates that no button is hold 219cb7a01acSMauro Carvalho Chehab down. 0xfe sequences are sometimes interrupted by 0xFF */ 220cb7a01acSMauro Carvalho Chehab 22150a762b4SSean Young dev_dbg(&ir->rc->dev, "key %02x\n", b); 222cb7a01acSMauro Carvalho Chehab 223cb7a01acSMauro Carvalho Chehab if (b == 0xff) 224cb7a01acSMauro Carvalho Chehab return 0; 225cb7a01acSMauro Carvalho Chehab 226cb7a01acSMauro Carvalho Chehab if (b == 0xfe) 227cb7a01acSMauro Carvalho Chehab /* keep old data */ 228cb7a01acSMauro Carvalho Chehab return 1; 229cb7a01acSMauro Carvalho Chehab 2306d741bfeSSean Young *protocol = RC_PROTO_UNKNOWN; 2314dd9bb91SDavid Härdeman *scancode = b; 2324dd9bb91SDavid Härdeman *toggle = 0; 233cb7a01acSMauro Carvalho Chehab return 1; 234cb7a01acSMauro Carvalho Chehab } 235cb7a01acSMauro Carvalho Chehab 2366d741bfeSSean Young static int get_key_avermedia_cardbus(struct IR_i2c *ir, enum rc_proto *protocol, 2374dd9bb91SDavid Härdeman u32 *scancode, u8 *toggle) 238cb7a01acSMauro Carvalho Chehab { 239cb7a01acSMauro Carvalho Chehab unsigned char subaddr, key, keygroup; 240cb7a01acSMauro Carvalho Chehab struct i2c_msg msg[] = { { .addr = ir->c->addr, .flags = 0, 241cb7a01acSMauro Carvalho Chehab .buf = &subaddr, .len = 1}, 242cb7a01acSMauro Carvalho Chehab { .addr = ir->c->addr, .flags = I2C_M_RD, 243cb7a01acSMauro Carvalho Chehab .buf = &key, .len = 1} }; 244cb7a01acSMauro Carvalho Chehab subaddr = 0x0d; 245cb7a01acSMauro Carvalho Chehab if (2 != i2c_transfer(ir->c->adapter, msg, 2)) { 24650a762b4SSean Young dev_dbg(&ir->rc->dev, "read error\n"); 247cb7a01acSMauro Carvalho Chehab return -EIO; 248cb7a01acSMauro Carvalho Chehab } 249cb7a01acSMauro Carvalho Chehab 250cb7a01acSMauro Carvalho Chehab if (key == 0xff) 251cb7a01acSMauro Carvalho Chehab return 0; 252cb7a01acSMauro Carvalho Chehab 253cb7a01acSMauro Carvalho Chehab subaddr = 0x0b; 254cb7a01acSMauro Carvalho Chehab msg[1].buf = &keygroup; 255cb7a01acSMauro Carvalho Chehab if (2 != i2c_transfer(ir->c->adapter, msg, 2)) { 25650a762b4SSean Young dev_dbg(&ir->rc->dev, "read error\n"); 257cb7a01acSMauro Carvalho Chehab return -EIO; 258cb7a01acSMauro Carvalho Chehab } 259cb7a01acSMauro Carvalho Chehab 260cb7a01acSMauro Carvalho Chehab if (keygroup == 0xff) 261cb7a01acSMauro Carvalho Chehab return 0; 262cb7a01acSMauro Carvalho Chehab 26350a762b4SSean Young dev_dbg(&ir->rc->dev, "read key 0x%02x/0x%02x\n", key, keygroup); 26434fe2784SOndrej Zary if (keygroup < 2 || keygroup > 4) { 26550a762b4SSean Young dev_warn(&ir->rc->dev, "warning: invalid key group 0x%02x for key 0x%02x\n", 266cb7a01acSMauro Carvalho Chehab keygroup, key); 267cb7a01acSMauro Carvalho Chehab } 268cb7a01acSMauro Carvalho Chehab key |= (keygroup & 1) << 6; 269cb7a01acSMauro Carvalho Chehab 2706d741bfeSSean Young *protocol = RC_PROTO_UNKNOWN; 2714dd9bb91SDavid Härdeman *scancode = key; 2724dd9bb91SDavid Härdeman if (ir->c->addr == 0x41) /* AVerMedia EM78P153 */ 2734dd9bb91SDavid Härdeman *scancode |= keygroup << 8; 2744dd9bb91SDavid Härdeman *toggle = 0; 275cb7a01acSMauro Carvalho Chehab return 1; 276cb7a01acSMauro Carvalho Chehab } 277cb7a01acSMauro Carvalho Chehab 278cb7a01acSMauro Carvalho Chehab /* ----------------------------------------------------------------------- */ 279cb7a01acSMauro Carvalho Chehab 280cb7a01acSMauro Carvalho Chehab static int ir_key_poll(struct IR_i2c *ir) 281cb7a01acSMauro Carvalho Chehab { 2826d741bfeSSean Young enum rc_proto protocol; 2834dd9bb91SDavid Härdeman u32 scancode; 2844dd9bb91SDavid Härdeman u8 toggle; 285cb7a01acSMauro Carvalho Chehab int rc; 286cb7a01acSMauro Carvalho Chehab 28750a762b4SSean Young dev_dbg(&ir->rc->dev, "%s\n", __func__); 2884dd9bb91SDavid Härdeman rc = ir->get_key(ir, &protocol, &scancode, &toggle); 289cb7a01acSMauro Carvalho Chehab if (rc < 0) { 29050a762b4SSean Young dev_warn(&ir->rc->dev, "error %d\n", rc); 291cb7a01acSMauro Carvalho Chehab return rc; 292cb7a01acSMauro Carvalho Chehab } 293cb7a01acSMauro Carvalho Chehab 294cb7a01acSMauro Carvalho Chehab if (rc) { 29550a762b4SSean Young dev_dbg(&ir->rc->dev, "%s: proto = 0x%04x, scancode = 0x%08x\n", 296120703f9SDavid Härdeman __func__, protocol, scancode); 297120703f9SDavid Härdeman rc_keydown(ir->rc, protocol, scancode, toggle); 298cb7a01acSMauro Carvalho Chehab } 299cb7a01acSMauro Carvalho Chehab return 0; 300cb7a01acSMauro Carvalho Chehab } 301cb7a01acSMauro Carvalho Chehab 302cb7a01acSMauro Carvalho Chehab static void ir_work(struct work_struct *work) 303cb7a01acSMauro Carvalho Chehab { 304cb7a01acSMauro Carvalho Chehab int rc; 305cb7a01acSMauro Carvalho Chehab struct IR_i2c *ir = container_of(work, struct IR_i2c, work.work); 306cb7a01acSMauro Carvalho Chehab 307*acaa34bfSSean Young /* 308*acaa34bfSSean Young * If the transmit code is holding the lock, skip polling for 309*acaa34bfSSean Young * IR, we'll get it to it next time round 310*acaa34bfSSean Young */ 311*acaa34bfSSean Young if (mutex_trylock(&ir->lock)) { 312cb7a01acSMauro Carvalho Chehab rc = ir_key_poll(ir); 313*acaa34bfSSean Young mutex_unlock(&ir->lock); 314cb7a01acSMauro Carvalho Chehab if (rc == -ENODEV) { 315cb7a01acSMauro Carvalho Chehab rc_unregister_device(ir->rc); 316cb7a01acSMauro Carvalho Chehab ir->rc = NULL; 317cb7a01acSMauro Carvalho Chehab return; 318cb7a01acSMauro Carvalho Chehab } 319*acaa34bfSSean Young } 320cb7a01acSMauro Carvalho Chehab 321cb7a01acSMauro Carvalho Chehab schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling_interval)); 322cb7a01acSMauro Carvalho Chehab } 323cb7a01acSMauro Carvalho Chehab 324a6927d81SSean Young static int ir_open(struct rc_dev *dev) 325a6927d81SSean Young { 326a6927d81SSean Young struct IR_i2c *ir = dev->priv; 327a6927d81SSean Young 328a6927d81SSean Young schedule_delayed_work(&ir->work, 0); 329a6927d81SSean Young 330a6927d81SSean Young return 0; 331a6927d81SSean Young } 332a6927d81SSean Young 333a6927d81SSean Young static void ir_close(struct rc_dev *dev) 334a6927d81SSean Young { 335a6927d81SSean Young struct IR_i2c *ir = dev->priv; 336a6927d81SSean Young 337a6927d81SSean Young cancel_delayed_work_sync(&ir->work); 338a6927d81SSean Young } 339a6927d81SSean Young 340*acaa34bfSSean Young /* Zilog Transmit Interface */ 341*acaa34bfSSean Young #define XTAL_FREQ 18432000 342*acaa34bfSSean Young 343*acaa34bfSSean Young #define ZILOG_SEND 0x80 344*acaa34bfSSean Young #define ZILOG_UIR_END 0x40 345*acaa34bfSSean Young #define ZILOG_INIT_END 0x20 346*acaa34bfSSean Young #define ZILOG_LIR_END 0x10 347*acaa34bfSSean Young 348*acaa34bfSSean Young #define ZILOG_STATUS_OK 0x80 349*acaa34bfSSean Young #define ZILOG_STATUS_TX 0x40 350*acaa34bfSSean Young #define ZILOG_STATUS_SET 0x20 351*acaa34bfSSean Young 352*acaa34bfSSean Young /* 353*acaa34bfSSean Young * As you can see here, very few different lengths of pulse and space 354*acaa34bfSSean Young * can be encoded. This means that the hardware does not work well with 355*acaa34bfSSean Young * recorded IR. It's best to work with generated IR, like from ir-ctl or 356*acaa34bfSSean Young * the in-kernel encoders. 357*acaa34bfSSean Young */ 358*acaa34bfSSean Young struct code_block { 359*acaa34bfSSean Young u8 length; 360*acaa34bfSSean Young u16 pulse[7]; /* not aligned */ 361*acaa34bfSSean Young u8 carrier_pulse; 362*acaa34bfSSean Young u8 carrier_space; 363*acaa34bfSSean Young u16 space[8]; /* not aligned */ 364*acaa34bfSSean Young u8 codes[61]; 365*acaa34bfSSean Young u8 csum[2]; 366*acaa34bfSSean Young } __packed; 367*acaa34bfSSean Young 368*acaa34bfSSean Young static int send_data_block(struct IR_i2c *ir, int cmd, 369*acaa34bfSSean Young struct code_block *code_block) 370*acaa34bfSSean Young { 371*acaa34bfSSean Young int i, j, ret; 372*acaa34bfSSean Young u8 buf[5], *p; 373*acaa34bfSSean Young 374*acaa34bfSSean Young p = &code_block->length; 375*acaa34bfSSean Young for (i = 0; p < code_block->csum; i++) 376*acaa34bfSSean Young code_block->csum[i & 1] ^= *p++; 377*acaa34bfSSean Young 378*acaa34bfSSean Young p = &code_block->length; 379*acaa34bfSSean Young 380*acaa34bfSSean Young for (i = 0; i < sizeof(*code_block);) { 381*acaa34bfSSean Young int tosend = sizeof(*code_block) - i; 382*acaa34bfSSean Young 383*acaa34bfSSean Young if (tosend > 4) 384*acaa34bfSSean Young tosend = 4; 385*acaa34bfSSean Young buf[0] = i + 1; 386*acaa34bfSSean Young for (j = 0; j < tosend; ++j) 387*acaa34bfSSean Young buf[1 + j] = p[i + j]; 388*acaa34bfSSean Young dev_dbg(&ir->rc->dev, "%*ph", tosend + 1, buf); 389*acaa34bfSSean Young ret = i2c_master_send(ir->tx_c, buf, tosend + 1); 390*acaa34bfSSean Young if (ret != tosend + 1) { 391*acaa34bfSSean Young dev_dbg(&ir->rc->dev, 392*acaa34bfSSean Young "i2c_master_send failed with %d\n", ret); 393*acaa34bfSSean Young return ret < 0 ? ret : -EIO; 394*acaa34bfSSean Young } 395*acaa34bfSSean Young i += tosend; 396*acaa34bfSSean Young } 397*acaa34bfSSean Young 398*acaa34bfSSean Young buf[0] = 0; 399*acaa34bfSSean Young buf[1] = cmd; 400*acaa34bfSSean Young ret = i2c_master_send(ir->tx_c, buf, 2); 401*acaa34bfSSean Young if (ret != 2) { 402*acaa34bfSSean Young dev_err(&ir->rc->dev, "i2c_master_send failed with %d\n", ret); 403*acaa34bfSSean Young return ret < 0 ? ret : -EIO; 404*acaa34bfSSean Young } 405*acaa34bfSSean Young 406*acaa34bfSSean Young usleep_range(2000, 5000); 407*acaa34bfSSean Young 408*acaa34bfSSean Young ret = i2c_master_send(ir->tx_c, buf, 1); 409*acaa34bfSSean Young if (ret != 1) { 410*acaa34bfSSean Young dev_err(&ir->rc->dev, "i2c_master_send failed with %d\n", ret); 411*acaa34bfSSean Young return ret < 0 ? ret : -EIO; 412*acaa34bfSSean Young } 413*acaa34bfSSean Young 414*acaa34bfSSean Young return 0; 415*acaa34bfSSean Young } 416*acaa34bfSSean Young 417*acaa34bfSSean Young static int zilog_init(struct IR_i2c *ir) 418*acaa34bfSSean Young { 419*acaa34bfSSean Young struct code_block code_block = { .length = sizeof(code_block) }; 420*acaa34bfSSean Young u8 buf[4]; 421*acaa34bfSSean Young int ret; 422*acaa34bfSSean Young 423*acaa34bfSSean Young put_unaligned_be16(0x1000, &code_block.pulse[3]); 424*acaa34bfSSean Young 425*acaa34bfSSean Young ret = send_data_block(ir, ZILOG_INIT_END, &code_block); 426*acaa34bfSSean Young if (ret) 427*acaa34bfSSean Young return ret; 428*acaa34bfSSean Young 429*acaa34bfSSean Young ret = i2c_master_recv(ir->tx_c, buf, 4); 430*acaa34bfSSean Young if (ret != 4) { 431*acaa34bfSSean Young dev_err(&ir->c->dev, "failed to retrieve firmware version: %d\n", 432*acaa34bfSSean Young ret); 433*acaa34bfSSean Young return ret < 0 ? ret : -EIO; 434*acaa34bfSSean Young } 435*acaa34bfSSean Young 436*acaa34bfSSean Young dev_info(&ir->c->dev, "Zilog/Hauppauge IR blaster firmware version %d.%d.%d\n", 437*acaa34bfSSean Young buf[1], buf[2], buf[3]); 438*acaa34bfSSean Young 439*acaa34bfSSean Young return 0; 440*acaa34bfSSean Young } 441*acaa34bfSSean Young 442*acaa34bfSSean Young /* 443*acaa34bfSSean Young * If the last slot for pulse is the same as the current slot for pulse, 444*acaa34bfSSean Young * then use slot no 7. 445*acaa34bfSSean Young */ 446*acaa34bfSSean Young static void copy_codes(u8 *dst, u8 *src, unsigned int count) 447*acaa34bfSSean Young { 448*acaa34bfSSean Young u8 c, last = 0xff; 449*acaa34bfSSean Young 450*acaa34bfSSean Young while (count--) { 451*acaa34bfSSean Young c = *src++; 452*acaa34bfSSean Young if ((c & 0xf0) == last) { 453*acaa34bfSSean Young *dst++ = 0x70 | (c & 0xf); 454*acaa34bfSSean Young } else { 455*acaa34bfSSean Young *dst++ = c; 456*acaa34bfSSean Young last = c & 0xf0; 457*acaa34bfSSean Young } 458*acaa34bfSSean Young } 459*acaa34bfSSean Young } 460*acaa34bfSSean Young 461*acaa34bfSSean Young /* 462*acaa34bfSSean Young * When looking for repeats, we don't care about the trailing space. This 463*acaa34bfSSean Young * is set to the shortest possible anyway. 464*acaa34bfSSean Young */ 465*acaa34bfSSean Young static int cmp_no_trail(u8 *a, u8 *b, unsigned int count) 466*acaa34bfSSean Young { 467*acaa34bfSSean Young while (--count) { 468*acaa34bfSSean Young if (*a++ != *b++) 469*acaa34bfSSean Young return 1; 470*acaa34bfSSean Young } 471*acaa34bfSSean Young 472*acaa34bfSSean Young return (*a & 0xf0) - (*b & 0xf0); 473*acaa34bfSSean Young } 474*acaa34bfSSean Young 475*acaa34bfSSean Young static int find_slot(u16 *array, unsigned int size, u16 val) 476*acaa34bfSSean Young { 477*acaa34bfSSean Young int i; 478*acaa34bfSSean Young 479*acaa34bfSSean Young for (i = 0; i < size; i++) { 480*acaa34bfSSean Young if (get_unaligned_be16(&array[i]) == val) { 481*acaa34bfSSean Young return i; 482*acaa34bfSSean Young } else if (!array[i]) { 483*acaa34bfSSean Young put_unaligned_be16(val, &array[i]); 484*acaa34bfSSean Young return i; 485*acaa34bfSSean Young } 486*acaa34bfSSean Young } 487*acaa34bfSSean Young 488*acaa34bfSSean Young return -1; 489*acaa34bfSSean Young } 490*acaa34bfSSean Young 491*acaa34bfSSean Young static int zilog_ir_format(struct rc_dev *rcdev, unsigned int *txbuf, 492*acaa34bfSSean Young unsigned int count, struct code_block *code_block) 493*acaa34bfSSean Young { 494*acaa34bfSSean Young struct IR_i2c *ir = rcdev->priv; 495*acaa34bfSSean Young int rep, i, l, p = 0, s, c = 0; 496*acaa34bfSSean Young bool repeating; 497*acaa34bfSSean Young u8 codes[174]; 498*acaa34bfSSean Young 499*acaa34bfSSean Young code_block->carrier_pulse = DIV_ROUND_CLOSEST( 500*acaa34bfSSean Young ir->duty_cycle * XTAL_FREQ / 1000, ir->carrier); 501*acaa34bfSSean Young code_block->carrier_space = DIV_ROUND_CLOSEST( 502*acaa34bfSSean Young (100 - ir->duty_cycle) * XTAL_FREQ / 1000, ir->carrier); 503*acaa34bfSSean Young 504*acaa34bfSSean Young for (i = 0; i < count; i++) { 505*acaa34bfSSean Young if (c >= ARRAY_SIZE(codes) - 1) { 506*acaa34bfSSean Young dev_warn(&rcdev->dev, "IR too long, cannot transmit\n"); 507*acaa34bfSSean Young return -EINVAL; 508*acaa34bfSSean Young } 509*acaa34bfSSean Young 510*acaa34bfSSean Young /* 511*acaa34bfSSean Young * Lengths more than 142220us cannot be encoded; also 512*acaa34bfSSean Young * this checks for multiply overflow 513*acaa34bfSSean Young */ 514*acaa34bfSSean Young if (txbuf[i] > 142220) 515*acaa34bfSSean Young return -EINVAL; 516*acaa34bfSSean Young 517*acaa34bfSSean Young l = DIV_ROUND_CLOSEST((XTAL_FREQ / 1000) * txbuf[i], 40000); 518*acaa34bfSSean Young 519*acaa34bfSSean Young if (i & 1) { 520*acaa34bfSSean Young s = find_slot(code_block->space, 521*acaa34bfSSean Young ARRAY_SIZE(code_block->space), l); 522*acaa34bfSSean Young if (s == -1) { 523*acaa34bfSSean Young dev_warn(&rcdev->dev, "Too many different lengths spaces, cannot transmit"); 524*acaa34bfSSean Young return -EINVAL; 525*acaa34bfSSean Young } 526*acaa34bfSSean Young 527*acaa34bfSSean Young /* We have a pulse and space */ 528*acaa34bfSSean Young codes[c++] = (p << 4) | s; 529*acaa34bfSSean Young } else { 530*acaa34bfSSean Young p = find_slot(code_block->pulse, 531*acaa34bfSSean Young ARRAY_SIZE(code_block->pulse), l); 532*acaa34bfSSean Young if (p == -1) { 533*acaa34bfSSean Young dev_warn(&rcdev->dev, "Too many different lengths pulses, cannot transmit"); 534*acaa34bfSSean Young return -EINVAL; 535*acaa34bfSSean Young } 536*acaa34bfSSean Young } 537*acaa34bfSSean Young } 538*acaa34bfSSean Young 539*acaa34bfSSean Young /* We have to encode the trailing pulse. Find the shortest space */ 540*acaa34bfSSean Young s = 0; 541*acaa34bfSSean Young for (i = 1; i < ARRAY_SIZE(code_block->space); i++) { 542*acaa34bfSSean Young u16 d = get_unaligned_be16(&code_block->space[i]); 543*acaa34bfSSean Young 544*acaa34bfSSean Young if (get_unaligned_be16(&code_block->space[s]) > d) 545*acaa34bfSSean Young s = i; 546*acaa34bfSSean Young } 547*acaa34bfSSean Young 548*acaa34bfSSean Young codes[c++] = (p << 4) | s; 549*acaa34bfSSean Young 550*acaa34bfSSean Young dev_dbg(&rcdev->dev, "generated %d codes\n", c); 551*acaa34bfSSean Young 552*acaa34bfSSean Young /* 553*acaa34bfSSean Young * Are the last N codes (so pulse + space) repeating 3 times? 554*acaa34bfSSean Young * if so we can shorten the codes list and use code 0xc0 to repeat 555*acaa34bfSSean Young * them. 556*acaa34bfSSean Young */ 557*acaa34bfSSean Young repeating = false; 558*acaa34bfSSean Young 559*acaa34bfSSean Young for (rep = c / 3; rep >= 1; rep--) { 560*acaa34bfSSean Young if (!memcmp(&codes[c - rep * 3], &codes[c - rep * 2], rep) && 561*acaa34bfSSean Young !cmp_no_trail(&codes[c - rep], &codes[c - rep * 2], rep)) { 562*acaa34bfSSean Young repeating = true; 563*acaa34bfSSean Young break; 564*acaa34bfSSean Young } 565*acaa34bfSSean Young } 566*acaa34bfSSean Young 567*acaa34bfSSean Young if (repeating) { 568*acaa34bfSSean Young /* first copy any leading non-repeating */ 569*acaa34bfSSean Young int leading = c - rep * 3; 570*acaa34bfSSean Young 571*acaa34bfSSean Young if (leading + rep >= ARRAY_SIZE(code_block->codes) - 3) { 572*acaa34bfSSean Young dev_warn(&rcdev->dev, "IR too long, cannot transmit\n"); 573*acaa34bfSSean Young return -EINVAL; 574*acaa34bfSSean Young } 575*acaa34bfSSean Young 576*acaa34bfSSean Young dev_dbg(&rcdev->dev, "found trailing %d repeat\n", rep); 577*acaa34bfSSean Young copy_codes(code_block->codes, codes, leading); 578*acaa34bfSSean Young code_block->codes[leading] = 0x82; 579*acaa34bfSSean Young copy_codes(code_block->codes + leading + 1, codes + leading, 580*acaa34bfSSean Young rep); 581*acaa34bfSSean Young c = leading + 1 + rep; 582*acaa34bfSSean Young code_block->codes[c++] = 0xc0; 583*acaa34bfSSean Young } else { 584*acaa34bfSSean Young if (c >= ARRAY_SIZE(code_block->codes) - 3) { 585*acaa34bfSSean Young dev_warn(&rcdev->dev, "IR too long, cannot transmit\n"); 586*acaa34bfSSean Young return -EINVAL; 587*acaa34bfSSean Young } 588*acaa34bfSSean Young 589*acaa34bfSSean Young dev_dbg(&rcdev->dev, "found no trailing repeat\n"); 590*acaa34bfSSean Young code_block->codes[0] = 0x82; 591*acaa34bfSSean Young copy_codes(code_block->codes + 1, codes, c); 592*acaa34bfSSean Young c++; 593*acaa34bfSSean Young code_block->codes[c++] = 0xc4; 594*acaa34bfSSean Young } 595*acaa34bfSSean Young 596*acaa34bfSSean Young while (c < ARRAY_SIZE(code_block->codes)) 597*acaa34bfSSean Young code_block->codes[c++] = 0x83; 598*acaa34bfSSean Young 599*acaa34bfSSean Young return 0; 600*acaa34bfSSean Young } 601*acaa34bfSSean Young 602*acaa34bfSSean Young static int zilog_tx(struct rc_dev *rcdev, unsigned int *txbuf, 603*acaa34bfSSean Young unsigned int count) 604*acaa34bfSSean Young { 605*acaa34bfSSean Young struct IR_i2c *ir = rcdev->priv; 606*acaa34bfSSean Young struct code_block code_block = { .length = sizeof(code_block) }; 607*acaa34bfSSean Young u8 buf[2]; 608*acaa34bfSSean Young int ret, i; 609*acaa34bfSSean Young 610*acaa34bfSSean Young ret = zilog_ir_format(rcdev, txbuf, count, &code_block); 611*acaa34bfSSean Young if (ret) 612*acaa34bfSSean Young return ret; 613*acaa34bfSSean Young 614*acaa34bfSSean Young ret = mutex_lock_interruptible(&ir->lock); 615*acaa34bfSSean Young if (ret) 616*acaa34bfSSean Young return ret; 617*acaa34bfSSean Young 618*acaa34bfSSean Young ret = send_data_block(ir, ZILOG_UIR_END, &code_block); 619*acaa34bfSSean Young if (ret) 620*acaa34bfSSean Young goto out_unlock; 621*acaa34bfSSean Young 622*acaa34bfSSean Young ret = i2c_master_recv(ir->tx_c, buf, 1); 623*acaa34bfSSean Young if (ret != 1) { 624*acaa34bfSSean Young dev_err(&ir->rc->dev, "i2c_master_recv failed with %d\n", ret); 625*acaa34bfSSean Young goto out_unlock; 626*acaa34bfSSean Young } 627*acaa34bfSSean Young 628*acaa34bfSSean Young dev_dbg(&ir->rc->dev, "code set status: %02x\n", buf[0]); 629*acaa34bfSSean Young 630*acaa34bfSSean Young if (buf[0] != (ZILOG_STATUS_OK | ZILOG_STATUS_SET)) { 631*acaa34bfSSean Young dev_err(&ir->rc->dev, "unexpected IR TX response %02x\n", 632*acaa34bfSSean Young buf[0]); 633*acaa34bfSSean Young ret = -EIO; 634*acaa34bfSSean Young goto out_unlock; 635*acaa34bfSSean Young } 636*acaa34bfSSean Young 637*acaa34bfSSean Young buf[0] = 0x00; 638*acaa34bfSSean Young buf[1] = ZILOG_SEND; 639*acaa34bfSSean Young 640*acaa34bfSSean Young ret = i2c_master_send(ir->tx_c, buf, 2); 641*acaa34bfSSean Young if (ret != 2) { 642*acaa34bfSSean Young dev_err(&ir->rc->dev, "i2c_master_send failed with %d\n", ret); 643*acaa34bfSSean Young if (ret >= 0) 644*acaa34bfSSean Young ret = -EIO; 645*acaa34bfSSean Young goto out_unlock; 646*acaa34bfSSean Young } 647*acaa34bfSSean Young 648*acaa34bfSSean Young dev_dbg(&ir->rc->dev, "send command sent\n"); 649*acaa34bfSSean Young 650*acaa34bfSSean Young /* 651*acaa34bfSSean Young * This bit NAKs until the device is ready, so we retry it 652*acaa34bfSSean Young * sleeping a bit each time. This seems to be what the windows 653*acaa34bfSSean Young * driver does, approximately. 654*acaa34bfSSean Young * Try for up to 1s. 655*acaa34bfSSean Young */ 656*acaa34bfSSean Young for (i = 0; i < 20; ++i) { 657*acaa34bfSSean Young set_current_state(TASK_UNINTERRUPTIBLE); 658*acaa34bfSSean Young schedule_timeout(msecs_to_jiffies(50)); 659*acaa34bfSSean Young ret = i2c_master_send(ir->tx_c, buf, 1); 660*acaa34bfSSean Young if (ret == 1) 661*acaa34bfSSean Young break; 662*acaa34bfSSean Young dev_dbg(&ir->rc->dev, 663*acaa34bfSSean Young "NAK expected: i2c_master_send failed with %d (try %d)\n", 664*acaa34bfSSean Young ret, i + 1); 665*acaa34bfSSean Young } 666*acaa34bfSSean Young 667*acaa34bfSSean Young if (ret != 1) { 668*acaa34bfSSean Young dev_err(&ir->rc->dev, 669*acaa34bfSSean Young "IR TX chip never got ready: last i2c_master_send failed with %d\n", 670*acaa34bfSSean Young ret); 671*acaa34bfSSean Young if (ret >= 0) 672*acaa34bfSSean Young ret = -EIO; 673*acaa34bfSSean Young goto out_unlock; 674*acaa34bfSSean Young } 675*acaa34bfSSean Young 676*acaa34bfSSean Young i = i2c_master_recv(ir->tx_c, buf, 1); 677*acaa34bfSSean Young if (i != 1) { 678*acaa34bfSSean Young dev_err(&ir->rc->dev, "i2c_master_recv failed with %d\n", ret); 679*acaa34bfSSean Young ret = -EIO; 680*acaa34bfSSean Young goto out_unlock; 681*acaa34bfSSean Young } else if (buf[0] != ZILOG_STATUS_OK) { 682*acaa34bfSSean Young dev_err(&ir->rc->dev, "unexpected IR TX response #2: %02x\n", 683*acaa34bfSSean Young buf[0]); 684*acaa34bfSSean Young ret = -EIO; 685*acaa34bfSSean Young goto out_unlock; 686*acaa34bfSSean Young } 687*acaa34bfSSean Young dev_dbg(&ir->rc->dev, "transmit complete\n"); 688*acaa34bfSSean Young 689*acaa34bfSSean Young /* Oh good, it worked */ 690*acaa34bfSSean Young ret = count; 691*acaa34bfSSean Young out_unlock: 692*acaa34bfSSean Young mutex_unlock(&ir->lock); 693*acaa34bfSSean Young 694*acaa34bfSSean Young return ret; 695*acaa34bfSSean Young } 696*acaa34bfSSean Young 697*acaa34bfSSean Young static int zilog_tx_carrier(struct rc_dev *dev, u32 carrier) 698*acaa34bfSSean Young { 699*acaa34bfSSean Young struct IR_i2c *ir = dev->priv; 700*acaa34bfSSean Young 701*acaa34bfSSean Young if (carrier > 500000 || carrier < 20000) 702*acaa34bfSSean Young return -EINVAL; 703*acaa34bfSSean Young 704*acaa34bfSSean Young ir->carrier = carrier; 705*acaa34bfSSean Young 706*acaa34bfSSean Young return 0; 707*acaa34bfSSean Young } 708*acaa34bfSSean Young 709*acaa34bfSSean Young static int zilog_tx_duty_cycle(struct rc_dev *dev, u32 duty_cycle) 710*acaa34bfSSean Young { 711*acaa34bfSSean Young struct IR_i2c *ir = dev->priv; 712*acaa34bfSSean Young 713*acaa34bfSSean Young ir->duty_cycle = duty_cycle; 714*acaa34bfSSean Young 715*acaa34bfSSean Young return 0; 716*acaa34bfSSean Young } 717cb7a01acSMauro Carvalho Chehab 718cb7a01acSMauro Carvalho Chehab static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) 719cb7a01acSMauro Carvalho Chehab { 720cb7a01acSMauro Carvalho Chehab char *ir_codes = NULL; 721cb7a01acSMauro Carvalho Chehab const char *name = NULL; 7226d741bfeSSean Young u64 rc_proto = RC_PROTO_BIT_UNKNOWN; 723cb7a01acSMauro Carvalho Chehab struct IR_i2c *ir; 724cb7a01acSMauro Carvalho Chehab struct rc_dev *rc = NULL; 725cb7a01acSMauro Carvalho Chehab struct i2c_adapter *adap = client->adapter; 726cb7a01acSMauro Carvalho Chehab unsigned short addr = client->addr; 727cb7a01acSMauro Carvalho Chehab int err; 728cb7a01acSMauro Carvalho Chehab 729c02b211dSLaurent Pinchart ir = devm_kzalloc(&client->dev, sizeof(*ir), GFP_KERNEL); 730cb7a01acSMauro Carvalho Chehab if (!ir) 731cb7a01acSMauro Carvalho Chehab return -ENOMEM; 732cb7a01acSMauro Carvalho Chehab 733cb7a01acSMauro Carvalho Chehab ir->c = client; 734cb7a01acSMauro Carvalho Chehab ir->polling_interval = DEFAULT_POLLING_INTERVAL; 735cb7a01acSMauro Carvalho Chehab i2c_set_clientdata(client, ir); 736cb7a01acSMauro Carvalho Chehab 737cb7a01acSMauro Carvalho Chehab switch(addr) { 738cb7a01acSMauro Carvalho Chehab case 0x64: 739cb7a01acSMauro Carvalho Chehab name = "Pixelview"; 740cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_pixelview; 7416d741bfeSSean Young rc_proto = RC_PROTO_BIT_OTHER; 742cb7a01acSMauro Carvalho Chehab ir_codes = RC_MAP_EMPTY; 743cb7a01acSMauro Carvalho Chehab break; 744cb7a01acSMauro Carvalho Chehab case 0x18: 745cb7a01acSMauro Carvalho Chehab case 0x1f: 746cb7a01acSMauro Carvalho Chehab case 0x1a: 747cb7a01acSMauro Carvalho Chehab name = "Hauppauge"; 748cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_haup; 7496d741bfeSSean Young rc_proto = RC_PROTO_BIT_RC5; 750cb7a01acSMauro Carvalho Chehab ir_codes = RC_MAP_HAUPPAUGE; 751cb7a01acSMauro Carvalho Chehab break; 752cb7a01acSMauro Carvalho Chehab case 0x30: 753cb7a01acSMauro Carvalho Chehab name = "KNC One"; 754cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_knc1; 7556d741bfeSSean Young rc_proto = RC_PROTO_BIT_OTHER; 756cb7a01acSMauro Carvalho Chehab ir_codes = RC_MAP_EMPTY; 757cb7a01acSMauro Carvalho Chehab break; 758cb7a01acSMauro Carvalho Chehab case 0x6b: 759cb7a01acSMauro Carvalho Chehab name = "FusionHDTV"; 760cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_fusionhdtv; 7616d741bfeSSean Young rc_proto = RC_PROTO_BIT_UNKNOWN; 762cb7a01acSMauro Carvalho Chehab ir_codes = RC_MAP_FUSIONHDTV_MCE; 763cb7a01acSMauro Carvalho Chehab break; 764cb7a01acSMauro Carvalho Chehab case 0x40: 765cb7a01acSMauro Carvalho Chehab name = "AVerMedia Cardbus remote"; 766cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_avermedia_cardbus; 7676d741bfeSSean Young rc_proto = RC_PROTO_BIT_OTHER; 768cb7a01acSMauro Carvalho Chehab ir_codes = RC_MAP_AVERMEDIA_CARDBUS; 769cb7a01acSMauro Carvalho Chehab break; 77034fe2784SOndrej Zary case 0x41: 77134fe2784SOndrej Zary name = "AVerMedia EM78P153"; 77234fe2784SOndrej Zary ir->get_key = get_key_avermedia_cardbus; 7736d741bfeSSean Young rc_proto = RC_PROTO_BIT_OTHER; 77434fe2784SOndrej Zary /* RM-KV remote, seems to be same as RM-K6 */ 77534fe2784SOndrej Zary ir_codes = RC_MAP_AVERMEDIA_M733A_RM_K6; 77634fe2784SOndrej Zary break; 777cb7a01acSMauro Carvalho Chehab case 0x71: 778cb7a01acSMauro Carvalho Chehab name = "Hauppauge/Zilog Z8"; 779cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_haup_xvr; 7806d741bfeSSean Young rc_proto = RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC6_MCE | 7816d741bfeSSean Young RC_PROTO_BIT_RC6_6A_32; 782cb7a01acSMauro Carvalho Chehab ir_codes = RC_MAP_HAUPPAUGE; 783cb7a01acSMauro Carvalho Chehab break; 784cb7a01acSMauro Carvalho Chehab } 785cb7a01acSMauro Carvalho Chehab 786cb7a01acSMauro Carvalho Chehab /* Let the caller override settings */ 787cb7a01acSMauro Carvalho Chehab if (client->dev.platform_data) { 788cb7a01acSMauro Carvalho Chehab const struct IR_i2c_init_data *init_data = 789cb7a01acSMauro Carvalho Chehab client->dev.platform_data; 790cb7a01acSMauro Carvalho Chehab 791cb7a01acSMauro Carvalho Chehab ir_codes = init_data->ir_codes; 792cb7a01acSMauro Carvalho Chehab rc = init_data->rc_dev; 793cb7a01acSMauro Carvalho Chehab 794cb7a01acSMauro Carvalho Chehab name = init_data->name; 795cb7a01acSMauro Carvalho Chehab if (init_data->type) 7966d741bfeSSean Young rc_proto = init_data->type; 797cb7a01acSMauro Carvalho Chehab 798cb7a01acSMauro Carvalho Chehab if (init_data->polling_interval) 799cb7a01acSMauro Carvalho Chehab ir->polling_interval = init_data->polling_interval; 800cb7a01acSMauro Carvalho Chehab 801cb7a01acSMauro Carvalho Chehab switch (init_data->internal_get_key_func) { 802cb7a01acSMauro Carvalho Chehab case IR_KBD_GET_KEY_CUSTOM: 803cb7a01acSMauro Carvalho Chehab /* The bridge driver provided us its own function */ 804cb7a01acSMauro Carvalho Chehab ir->get_key = init_data->get_key; 805cb7a01acSMauro Carvalho Chehab break; 806cb7a01acSMauro Carvalho Chehab case IR_KBD_GET_KEY_PIXELVIEW: 807cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_pixelview; 808cb7a01acSMauro Carvalho Chehab break; 809cb7a01acSMauro Carvalho Chehab case IR_KBD_GET_KEY_HAUP: 810cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_haup; 811cb7a01acSMauro Carvalho Chehab break; 812cb7a01acSMauro Carvalho Chehab case IR_KBD_GET_KEY_KNC1: 813cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_knc1; 814cb7a01acSMauro Carvalho Chehab break; 815cb7a01acSMauro Carvalho Chehab case IR_KBD_GET_KEY_FUSIONHDTV: 816cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_fusionhdtv; 817cb7a01acSMauro Carvalho Chehab break; 818cb7a01acSMauro Carvalho Chehab case IR_KBD_GET_KEY_HAUP_XVR: 819cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_haup_xvr; 820cb7a01acSMauro Carvalho Chehab break; 821cb7a01acSMauro Carvalho Chehab case IR_KBD_GET_KEY_AVERMEDIA_CARDBUS: 822cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_avermedia_cardbus; 823cb7a01acSMauro Carvalho Chehab break; 824cb7a01acSMauro Carvalho Chehab } 825cb7a01acSMauro Carvalho Chehab } 826cb7a01acSMauro Carvalho Chehab 827cb7a01acSMauro Carvalho Chehab if (!rc) { 828cb7a01acSMauro Carvalho Chehab /* 82939c1cb2bSJonathan McCrohan * If platform_data doesn't specify rc_dev, initialize it 830cb7a01acSMauro Carvalho Chehab * internally 831cb7a01acSMauro Carvalho Chehab */ 8320f7499fdSAndi Shyti rc = rc_allocate_device(RC_DRIVER_SCANCODE); 833c02b211dSLaurent Pinchart if (!rc) 834c02b211dSLaurent Pinchart return -ENOMEM; 835cb7a01acSMauro Carvalho Chehab } 836cb7a01acSMauro Carvalho Chehab ir->rc = rc; 837cb7a01acSMauro Carvalho Chehab 838cb7a01acSMauro Carvalho Chehab /* Make sure we are all setup before going on */ 8396d741bfeSSean Young if (!name || !ir->get_key || !rc_proto || !ir_codes) { 84050a762b4SSean Young dev_warn(&client->dev, "Unsupported device at address 0x%02x\n", 841cb7a01acSMauro Carvalho Chehab addr); 842cb7a01acSMauro Carvalho Chehab err = -ENODEV; 843cb7a01acSMauro Carvalho Chehab goto err_out_free; 844cb7a01acSMauro Carvalho Chehab } 845cb7a01acSMauro Carvalho Chehab 846cb7a01acSMauro Carvalho Chehab ir->ir_codes = ir_codes; 847cb7a01acSMauro Carvalho Chehab 848afc7f24cSSean Young snprintf(ir->phys, sizeof(ir->phys), "%s/%s", dev_name(&adap->dev), 849cb7a01acSMauro Carvalho Chehab dev_name(&client->dev)); 850cb7a01acSMauro Carvalho Chehab 851cb7a01acSMauro Carvalho Chehab /* 852cb7a01acSMauro Carvalho Chehab * Initialize input_dev fields 853cb7a01acSMauro Carvalho Chehab * It doesn't make sense to allow overriding them via platform_data 854cb7a01acSMauro Carvalho Chehab */ 855cb7a01acSMauro Carvalho Chehab rc->input_id.bustype = BUS_I2C; 856cb7a01acSMauro Carvalho Chehab rc->input_phys = ir->phys; 857afc7f24cSSean Young rc->device_name = name; 858afc7f24cSSean Young rc->dev.parent = &client->dev; 859a6927d81SSean Young rc->priv = ir; 860a6927d81SSean Young rc->open = ir_open; 861a6927d81SSean Young rc->close = ir_close; 862cb7a01acSMauro Carvalho Chehab 863cb7a01acSMauro Carvalho Chehab /* 864cb7a01acSMauro Carvalho Chehab * Initialize the other fields of rc_dev 865cb7a01acSMauro Carvalho Chehab */ 866cb7a01acSMauro Carvalho Chehab rc->map_name = ir->ir_codes; 8676d741bfeSSean Young rc->allowed_protocols = rc_proto; 868cb7a01acSMauro Carvalho Chehab if (!rc->driver_name) 86950a762b4SSean Young rc->driver_name = KBUILD_MODNAME; 870cb7a01acSMauro Carvalho Chehab 871*acaa34bfSSean Young mutex_init(&ir->lock); 872*acaa34bfSSean Young 873a6927d81SSean Young INIT_DELAYED_WORK(&ir->work, ir_work); 874a6927d81SSean Young 875*acaa34bfSSean Young if (id->driver_data & FLAG_TX) { 876*acaa34bfSSean Young ir->tx_c = i2c_new_dummy(client->adapter, 0x70); 877*acaa34bfSSean Young if (!ir->tx_c) { 878*acaa34bfSSean Young dev_err(&client->dev, "failed to setup tx i2c address"); 879*acaa34bfSSean Young } else if (!zilog_init(ir)) { 880*acaa34bfSSean Young ir->carrier = 38000; 881*acaa34bfSSean Young ir->duty_cycle = 40; 882*acaa34bfSSean Young rc->tx_ir = zilog_tx; 883*acaa34bfSSean Young rc->s_tx_carrier = zilog_tx_carrier; 884*acaa34bfSSean Young rc->s_tx_duty_cycle = zilog_tx_duty_cycle; 885*acaa34bfSSean Young } 886*acaa34bfSSean Young } 887*acaa34bfSSean Young 888cb7a01acSMauro Carvalho Chehab err = rc_register_device(rc); 889cb7a01acSMauro Carvalho Chehab if (err) 890cb7a01acSMauro Carvalho Chehab goto err_out_free; 891cb7a01acSMauro Carvalho Chehab 892cb7a01acSMauro Carvalho Chehab return 0; 893cb7a01acSMauro Carvalho Chehab 894cb7a01acSMauro Carvalho Chehab err_out_free: 895*acaa34bfSSean Young if (ir->tx_c) 896*acaa34bfSSean Young i2c_unregister_device(ir->tx_c); 897*acaa34bfSSean Young 898cb7a01acSMauro Carvalho Chehab /* Only frees rc if it were allocated internally */ 899cb7a01acSMauro Carvalho Chehab rc_free_device(rc); 900cb7a01acSMauro Carvalho Chehab return err; 901cb7a01acSMauro Carvalho Chehab } 902cb7a01acSMauro Carvalho Chehab 903cb7a01acSMauro Carvalho Chehab static int ir_remove(struct i2c_client *client) 904cb7a01acSMauro Carvalho Chehab { 905cb7a01acSMauro Carvalho Chehab struct IR_i2c *ir = i2c_get_clientdata(client); 906cb7a01acSMauro Carvalho Chehab 907cb7a01acSMauro Carvalho Chehab /* kill outstanding polls */ 908cb7a01acSMauro Carvalho Chehab cancel_delayed_work_sync(&ir->work); 909cb7a01acSMauro Carvalho Chehab 910*acaa34bfSSean Young if (ir->tx_c) 911*acaa34bfSSean Young i2c_unregister_device(ir->tx_c); 912*acaa34bfSSean Young 913cb7a01acSMauro Carvalho Chehab /* unregister device */ 914cb7a01acSMauro Carvalho Chehab rc_unregister_device(ir->rc); 915cb7a01acSMauro Carvalho Chehab 916cb7a01acSMauro Carvalho Chehab /* free memory */ 917cb7a01acSMauro Carvalho Chehab return 0; 918cb7a01acSMauro Carvalho Chehab } 919cb7a01acSMauro Carvalho Chehab 920cb7a01acSMauro Carvalho Chehab static const struct i2c_device_id ir_kbd_id[] = { 921cb7a01acSMauro Carvalho Chehab /* Generic entry for any IR receiver */ 922cb7a01acSMauro Carvalho Chehab { "ir_video", 0 }, 923cb7a01acSMauro Carvalho Chehab /* IR device specific entries should be added here */ 924*acaa34bfSSean Young { "ir_z8f0811_haup", FLAG_TX }, 925*acaa34bfSSean Young { "ir_z8f0811_hdpvr", FLAG_TX | FLAG_HDPVR }, 926cb7a01acSMauro Carvalho Chehab { } 927cb7a01acSMauro Carvalho Chehab }; 928cb7a01acSMauro Carvalho Chehab 929cb7a01acSMauro Carvalho Chehab static struct i2c_driver ir_kbd_driver = { 930cb7a01acSMauro Carvalho Chehab .driver = { 931cb7a01acSMauro Carvalho Chehab .name = "ir-kbd-i2c", 932cb7a01acSMauro Carvalho Chehab }, 933cb7a01acSMauro Carvalho Chehab .probe = ir_probe, 934cb7a01acSMauro Carvalho Chehab .remove = ir_remove, 935cb7a01acSMauro Carvalho Chehab .id_table = ir_kbd_id, 936cb7a01acSMauro Carvalho Chehab }; 937cb7a01acSMauro Carvalho Chehab 938cb7a01acSMauro Carvalho Chehab module_i2c_driver(ir_kbd_driver); 939cb7a01acSMauro Carvalho Chehab 940cb7a01acSMauro Carvalho Chehab /* ----------------------------------------------------------------------- */ 941cb7a01acSMauro Carvalho Chehab 942cb7a01acSMauro Carvalho Chehab MODULE_AUTHOR("Gerd Knorr, Michal Kochanowicz, Christoph Bartelmus, Ulrich Mueller"); 943cb7a01acSMauro Carvalho Chehab MODULE_DESCRIPTION("input driver for i2c IR remote controls"); 944cb7a01acSMauro Carvalho Chehab MODULE_LICENSE("GPL"); 945