13ef9dff4SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2cb7a01acSMauro Carvalho Chehab /* 3cb7a01acSMauro Carvalho Chehab * 4cb7a01acSMauro Carvalho Chehab * keyboard input driver for i2c IR remote controls 5cb7a01acSMauro Carvalho Chehab * 6cb7a01acSMauro Carvalho Chehab * Copyright (c) 2000-2003 Gerd Knorr <kraxel@bytesex.org> 7cb7a01acSMauro Carvalho Chehab * modified for PixelView (BT878P+W/FM) by 8cb7a01acSMauro Carvalho Chehab * Michal Kochanowicz <mkochano@pld.org.pl> 9cb7a01acSMauro Carvalho Chehab * Christoph Bartelmus <lirc@bartelmus.de> 10cb7a01acSMauro Carvalho Chehab * modified for KNC ONE TV Station/Anubis Typhoon TView Tuner by 11cb7a01acSMauro Carvalho Chehab * Ulrich Mueller <ulrich.mueller42@web.de> 12cb7a01acSMauro Carvalho Chehab * modified for em2820 based USB TV tuners by 13cb7a01acSMauro Carvalho Chehab * Markus Rechberger <mrechberger@gmail.com> 14cb7a01acSMauro Carvalho Chehab * modified for DViCO Fusion HDTV 5 RT GOLD by 15cb7a01acSMauro Carvalho Chehab * Chaogui Zhang <czhang1974@gmail.com> 16cb7a01acSMauro Carvalho Chehab * modified for MSI TV@nywhere Plus by 17cb7a01acSMauro Carvalho Chehab * Henry Wong <henry@stuffedcow.net> 18cb7a01acSMauro Carvalho Chehab * Mark Schultz <n9xmj@yahoo.com> 19cb7a01acSMauro Carvalho Chehab * Brian Rogers <brian_rogers@comcast.net> 20cb7a01acSMauro Carvalho Chehab * modified for AVerMedia Cardbus by 21cb7a01acSMauro Carvalho Chehab * Oldrich Jedlicka <oldium.pro@seznam.cz> 22acaa34bfSSean Young * Zilog Transmitter portions/ideas were derived from GPLv2+ sources: 23acaa34bfSSean Young * - drivers/char/pctv_zilogir.[ch] from Hauppauge Broadway product 24acaa34bfSSean Young * Copyright 2011 Hauppauge Computer works 25acaa34bfSSean Young * - drivers/staging/media/lirc/lirc_zilog.c 26acaa34bfSSean Young * Copyright (c) 2000 Gerd Knorr <kraxel@goldbach.in-berlin.de> 27acaa34bfSSean Young * Michal Kochanowicz <mkochano@pld.org.pl> 28acaa34bfSSean Young * Christoph Bartelmus <lirc@bartelmus.de> 29acaa34bfSSean Young * Ulrich Mueller <ulrich.mueller42@web.de> 30acaa34bfSSean Young * Stefan Jahn <stefan@lkcc.org> 31acaa34bfSSean Young * Jerome Brock <jbrock@users.sourceforge.net> 32acaa34bfSSean Young * Thomas Reitmayr (treitmayr@yahoo.com) 33acaa34bfSSean Young * Mark Weaver <mark@npsl.co.uk> 34acaa34bfSSean Young * Jarod Wilson <jarod@redhat.com> 35acaa34bfSSean Young * Copyright (C) 2011 Andy Walls <awalls@md.metrocast.net> 36cb7a01acSMauro Carvalho Chehab */ 37cb7a01acSMauro Carvalho Chehab 3800bb8207SSean Young #include <asm/unaligned.h> 39cb7a01acSMauro Carvalho Chehab #include <linux/module.h> 40cb7a01acSMauro Carvalho Chehab #include <linux/init.h> 41cb7a01acSMauro Carvalho Chehab #include <linux/kernel.h> 42cb7a01acSMauro Carvalho Chehab #include <linux/string.h> 43cb7a01acSMauro Carvalho Chehab #include <linux/timer.h> 44cb7a01acSMauro Carvalho Chehab #include <linux/delay.h> 45cb7a01acSMauro Carvalho Chehab #include <linux/errno.h> 46cb7a01acSMauro Carvalho Chehab #include <linux/slab.h> 47cb7a01acSMauro Carvalho Chehab #include <linux/i2c.h> 48cb7a01acSMauro Carvalho Chehab #include <linux/workqueue.h> 49cb7a01acSMauro Carvalho Chehab 50cb7a01acSMauro Carvalho Chehab #include <media/rc-core.h> 51b5dcee22SMauro Carvalho Chehab #include <media/i2c/ir-kbd-i2c.h> 52cb7a01acSMauro Carvalho Chehab 53acaa34bfSSean Young #define FLAG_TX 1 54acaa34bfSSean Young #define FLAG_HDPVR 2 55cb7a01acSMauro Carvalho Chehab 561cb26030SSean Young static bool enable_hdpvr; 571cb26030SSean Young module_param(enable_hdpvr, bool, 0644); 581cb26030SSean Young 596d741bfeSSean Young static int get_key_haup_common(struct IR_i2c *ir, enum rc_proto *protocol, 6000bb8207SSean Young u32 *scancode, u8 *ptoggle, int size) 61cb7a01acSMauro Carvalho Chehab { 62cb7a01acSMauro Carvalho Chehab unsigned char buf[6]; 6300bb8207SSean Young int start, range, toggle, dev, code, ircode, vendor; 64cb7a01acSMauro Carvalho Chehab 65cb7a01acSMauro Carvalho Chehab /* poll IR chip */ 66cb7a01acSMauro Carvalho Chehab if (size != i2c_master_recv(ir->c, buf, size)) 67cb7a01acSMauro Carvalho Chehab return -EIO; 68cb7a01acSMauro Carvalho Chehab 6900bb8207SSean Young if (buf[0] & 0x80) { 7000bb8207SSean Young int offset = (size == 6) ? 3 : 0; 7100bb8207SSean Young 72cb7a01acSMauro Carvalho Chehab /* split rc5 data block ... */ 73cb7a01acSMauro Carvalho Chehab start = (buf[offset] >> 7) & 1; 74cb7a01acSMauro Carvalho Chehab range = (buf[offset] >> 6) & 1; 75cb7a01acSMauro Carvalho Chehab toggle = (buf[offset] >> 5) & 1; 76cb7a01acSMauro Carvalho Chehab dev = buf[offset] & 0x1f; 77cb7a01acSMauro Carvalho Chehab code = (buf[offset+1] >> 2) & 0x3f; 78cb7a01acSMauro Carvalho Chehab 79cb7a01acSMauro Carvalho Chehab /* rc5 has two start bits 80cb7a01acSMauro Carvalho Chehab * the first bit must be one 8100bb8207SSean Young * the second bit defines the command range: 8200bb8207SSean Young * 1 = 0-63, 0 = 64 - 127 83cb7a01acSMauro Carvalho Chehab */ 84cb7a01acSMauro Carvalho Chehab if (!start) 85cb7a01acSMauro Carvalho Chehab /* no key pressed */ 86cb7a01acSMauro Carvalho Chehab return 0; 874dd9bb91SDavid Härdeman 884dd9bb91SDavid Härdeman /* filter out invalid key presses */ 89cb7a01acSMauro Carvalho Chehab ircode = (start << 12) | (toggle << 11) | (dev << 6) | code; 90cb7a01acSMauro Carvalho Chehab if ((ircode & 0x1fff) == 0x1fff) 91cb7a01acSMauro Carvalho Chehab return 0; 92cb7a01acSMauro Carvalho Chehab 93cb7a01acSMauro Carvalho Chehab if (!range) 94cb7a01acSMauro Carvalho Chehab code += 64; 95cb7a01acSMauro Carvalho Chehab 9650a762b4SSean Young dev_dbg(&ir->rc->dev, 9750a762b4SSean Young "ir hauppauge (rc5): s%d r%d t%d dev=%d code=%d\n", 98cb7a01acSMauro Carvalho Chehab start, range, toggle, dev, code); 99cb7a01acSMauro Carvalho Chehab 1006d741bfeSSean Young *protocol = RC_PROTO_RC5; 1014dd9bb91SDavid Härdeman *scancode = RC_SCANCODE_RC5(dev, code); 1024dd9bb91SDavid Härdeman *ptoggle = toggle; 10300bb8207SSean Young 104cb7a01acSMauro Carvalho Chehab return 1; 10500bb8207SSean Young } else if (size == 6 && (buf[0] & 0x40)) { 10600bb8207SSean Young code = buf[4]; 10700bb8207SSean Young dev = buf[3]; 10800bb8207SSean Young vendor = get_unaligned_be16(buf + 1); 10900bb8207SSean Young 11000bb8207SSean Young if (vendor == 0x800f) { 11100bb8207SSean Young *ptoggle = (dev & 0x80) != 0; 1126d741bfeSSean Young *protocol = RC_PROTO_RC6_MCE; 11300bb8207SSean Young dev &= 0x7f; 11450a762b4SSean Young dev_dbg(&ir->rc->dev, 11550a762b4SSean Young "ir hauppauge (rc6-mce): t%d vendor=%d dev=%d code=%d\n", 1169cdbe14fSArnd Bergmann *ptoggle, vendor, dev, code); 11700bb8207SSean Young } else { 11800bb8207SSean Young *ptoggle = 0; 1196d741bfeSSean Young *protocol = RC_PROTO_RC6_6A_32; 12050a762b4SSean Young dev_dbg(&ir->rc->dev, 12150a762b4SSean Young "ir hauppauge (rc6-6a-32): vendor=%d dev=%d code=%d\n", 12200bb8207SSean Young vendor, dev, code); 12300bb8207SSean Young } 12400bb8207SSean Young 12500bb8207SSean Young *scancode = RC_SCANCODE_RC6_6A(vendor, dev, code); 12600bb8207SSean Young 12700bb8207SSean Young return 1; 12800bb8207SSean Young } 12900bb8207SSean Young 13000bb8207SSean Young return 0; 131cb7a01acSMauro Carvalho Chehab } 132cb7a01acSMauro Carvalho Chehab 1336d741bfeSSean Young static int get_key_haup(struct IR_i2c *ir, enum rc_proto *protocol, 1344dd9bb91SDavid Härdeman u32 *scancode, u8 *toggle) 135cb7a01acSMauro Carvalho Chehab { 13600bb8207SSean Young return get_key_haup_common(ir, protocol, scancode, toggle, 3); 137cb7a01acSMauro Carvalho Chehab } 138cb7a01acSMauro Carvalho Chehab 1396d741bfeSSean Young static int get_key_haup_xvr(struct IR_i2c *ir, enum rc_proto *protocol, 1404dd9bb91SDavid Härdeman u32 *scancode, u8 *toggle) 141cb7a01acSMauro Carvalho Chehab { 142cb7a01acSMauro Carvalho Chehab int ret; 143cb7a01acSMauro Carvalho Chehab unsigned char buf[1] = { 0 }; 144cb7a01acSMauro Carvalho Chehab 145cb7a01acSMauro Carvalho Chehab /* 146cb7a01acSMauro Carvalho Chehab * This is the same apparent "are you ready?" poll command observed 147cb7a01acSMauro Carvalho Chehab * watching Windows driver traffic and implemented in lirc_zilog. With 148cb7a01acSMauro Carvalho Chehab * this added, we get far saner remote behavior with z8 chips on usb 149cb7a01acSMauro Carvalho Chehab * connected devices, even with the default polling interval of 100ms. 150cb7a01acSMauro Carvalho Chehab */ 151cb7a01acSMauro Carvalho Chehab ret = i2c_master_send(ir->c, buf, 1); 152cb7a01acSMauro Carvalho Chehab if (ret != 1) 153cb7a01acSMauro Carvalho Chehab return (ret < 0) ? ret : -EINVAL; 154cb7a01acSMauro Carvalho Chehab 15500bb8207SSean Young return get_key_haup_common(ir, protocol, scancode, toggle, 6); 156cb7a01acSMauro Carvalho Chehab } 157cb7a01acSMauro Carvalho Chehab 1586d741bfeSSean Young static int get_key_pixelview(struct IR_i2c *ir, enum rc_proto *protocol, 1594dd9bb91SDavid Härdeman u32 *scancode, u8 *toggle) 160cb7a01acSMauro Carvalho Chehab { 161c3902dabSMauro Carvalho Chehab int rc; 162cb7a01acSMauro Carvalho Chehab unsigned char b; 163cb7a01acSMauro Carvalho Chehab 164cb7a01acSMauro Carvalho Chehab /* poll IR chip */ 165c3902dabSMauro Carvalho Chehab rc = i2c_master_recv(ir->c, &b, 1); 166c3902dabSMauro Carvalho Chehab if (rc != 1) { 16750a762b4SSean Young dev_dbg(&ir->rc->dev, "read error\n"); 168c3902dabSMauro Carvalho Chehab if (rc < 0) 169c3902dabSMauro Carvalho Chehab return rc; 170cb7a01acSMauro Carvalho Chehab return -EIO; 171cb7a01acSMauro Carvalho Chehab } 1724dd9bb91SDavid Härdeman 1736d741bfeSSean Young *protocol = RC_PROTO_OTHER; 1744dd9bb91SDavid Härdeman *scancode = b; 1754dd9bb91SDavid Härdeman *toggle = 0; 176cb7a01acSMauro Carvalho Chehab return 1; 177cb7a01acSMauro Carvalho Chehab } 178cb7a01acSMauro Carvalho Chehab 1796d741bfeSSean Young static int get_key_fusionhdtv(struct IR_i2c *ir, enum rc_proto *protocol, 1804dd9bb91SDavid Härdeman u32 *scancode, u8 *toggle) 181cb7a01acSMauro Carvalho Chehab { 182c3902dabSMauro Carvalho Chehab int rc; 183cb7a01acSMauro Carvalho Chehab unsigned char buf[4]; 184cb7a01acSMauro Carvalho Chehab 185cb7a01acSMauro Carvalho Chehab /* poll IR chip */ 186c3902dabSMauro Carvalho Chehab rc = i2c_master_recv(ir->c, buf, 4); 187c3902dabSMauro Carvalho Chehab if (rc != 4) { 18850a762b4SSean Young dev_dbg(&ir->rc->dev, "read error\n"); 189c3902dabSMauro Carvalho Chehab if (rc < 0) 190c3902dabSMauro Carvalho Chehab return rc; 191cb7a01acSMauro Carvalho Chehab return -EIO; 192cb7a01acSMauro Carvalho Chehab } 193cb7a01acSMauro Carvalho Chehab 194cb7a01acSMauro Carvalho Chehab if (buf[0] != 0 || buf[1] != 0 || buf[2] != 0 || buf[3] != 0) 19550a762b4SSean Young dev_dbg(&ir->rc->dev, "%s: %*ph\n", __func__, 4, buf); 196cb7a01acSMauro Carvalho Chehab 197cb7a01acSMauro Carvalho Chehab /* no key pressed or signal from other ir remote */ 198cb7a01acSMauro Carvalho Chehab if(buf[0] != 0x1 || buf[1] != 0xfe) 199cb7a01acSMauro Carvalho Chehab return 0; 200cb7a01acSMauro Carvalho Chehab 2016d741bfeSSean Young *protocol = RC_PROTO_UNKNOWN; 2024dd9bb91SDavid Härdeman *scancode = buf[2]; 2034dd9bb91SDavid Härdeman *toggle = 0; 204cb7a01acSMauro Carvalho Chehab return 1; 205cb7a01acSMauro Carvalho Chehab } 206cb7a01acSMauro Carvalho Chehab 2076d741bfeSSean Young static int get_key_knc1(struct IR_i2c *ir, enum rc_proto *protocol, 2084dd9bb91SDavid Härdeman u32 *scancode, u8 *toggle) 209cb7a01acSMauro Carvalho Chehab { 210c3902dabSMauro Carvalho Chehab int rc; 211cb7a01acSMauro Carvalho Chehab unsigned char b; 212cb7a01acSMauro Carvalho Chehab 213cb7a01acSMauro Carvalho Chehab /* poll IR chip */ 214c3902dabSMauro Carvalho Chehab rc = i2c_master_recv(ir->c, &b, 1); 215c3902dabSMauro Carvalho Chehab if (rc != 1) { 21650a762b4SSean Young dev_dbg(&ir->rc->dev, "read error\n"); 217c3902dabSMauro Carvalho Chehab if (rc < 0) 218c3902dabSMauro Carvalho Chehab return rc; 219cb7a01acSMauro Carvalho Chehab return -EIO; 220cb7a01acSMauro Carvalho Chehab } 221cb7a01acSMauro Carvalho Chehab 222cb7a01acSMauro Carvalho Chehab /* it seems that 0xFE indicates that a button is still hold 223cb7a01acSMauro Carvalho Chehab down, while 0xff indicates that no button is hold 224cb7a01acSMauro Carvalho Chehab down. 0xfe sequences are sometimes interrupted by 0xFF */ 225cb7a01acSMauro Carvalho Chehab 22650a762b4SSean Young dev_dbg(&ir->rc->dev, "key %02x\n", b); 227cb7a01acSMauro Carvalho Chehab 228cb7a01acSMauro Carvalho Chehab if (b == 0xff) 229cb7a01acSMauro Carvalho Chehab return 0; 230cb7a01acSMauro Carvalho Chehab 231cb7a01acSMauro Carvalho Chehab if (b == 0xfe) 232cb7a01acSMauro Carvalho Chehab /* keep old data */ 233cb7a01acSMauro Carvalho Chehab return 1; 234cb7a01acSMauro Carvalho Chehab 2356d741bfeSSean Young *protocol = RC_PROTO_UNKNOWN; 2364dd9bb91SDavid Härdeman *scancode = b; 2374dd9bb91SDavid Härdeman *toggle = 0; 238cb7a01acSMauro Carvalho Chehab return 1; 239cb7a01acSMauro Carvalho Chehab } 240cb7a01acSMauro Carvalho Chehab 24139dfd52dSDaniel González Cabanelas static int get_key_geniatech(struct IR_i2c *ir, enum rc_proto *protocol, 24239dfd52dSDaniel González Cabanelas u32 *scancode, u8 *toggle) 24339dfd52dSDaniel González Cabanelas { 24439dfd52dSDaniel González Cabanelas int i, rc; 24539dfd52dSDaniel González Cabanelas unsigned char b; 24639dfd52dSDaniel González Cabanelas 24739dfd52dSDaniel González Cabanelas /* poll IR chip */ 24839dfd52dSDaniel González Cabanelas for (i = 0; i < 4; i++) { 24939dfd52dSDaniel González Cabanelas rc = i2c_master_recv(ir->c, &b, 1); 25039dfd52dSDaniel González Cabanelas if (rc == 1) 25139dfd52dSDaniel González Cabanelas break; 25239dfd52dSDaniel González Cabanelas msleep(20); 25339dfd52dSDaniel González Cabanelas } 25439dfd52dSDaniel González Cabanelas if (rc != 1) { 25539dfd52dSDaniel González Cabanelas dev_dbg(&ir->rc->dev, "read error\n"); 25639dfd52dSDaniel González Cabanelas if (rc < 0) 25739dfd52dSDaniel González Cabanelas return rc; 25839dfd52dSDaniel González Cabanelas return -EIO; 25939dfd52dSDaniel González Cabanelas } 26039dfd52dSDaniel González Cabanelas 26139dfd52dSDaniel González Cabanelas /* don't repeat the key */ 26239dfd52dSDaniel González Cabanelas if (ir->old == b) 26339dfd52dSDaniel González Cabanelas return 0; 26439dfd52dSDaniel González Cabanelas ir->old = b; 26539dfd52dSDaniel González Cabanelas 26639dfd52dSDaniel González Cabanelas /* decode to RC5 */ 26739dfd52dSDaniel González Cabanelas b &= 0x7f; 26839dfd52dSDaniel González Cabanelas b = (b - 1) / 2; 26939dfd52dSDaniel González Cabanelas 27039dfd52dSDaniel González Cabanelas dev_dbg(&ir->rc->dev, "key %02x\n", b); 27139dfd52dSDaniel González Cabanelas 27239dfd52dSDaniel González Cabanelas *protocol = RC_PROTO_RC5; 27339dfd52dSDaniel González Cabanelas *scancode = b; 27439dfd52dSDaniel González Cabanelas *toggle = ir->old >> 7; 27539dfd52dSDaniel González Cabanelas return 1; 27639dfd52dSDaniel González Cabanelas } 27739dfd52dSDaniel González Cabanelas 2786d741bfeSSean Young static int get_key_avermedia_cardbus(struct IR_i2c *ir, enum rc_proto *protocol, 2794dd9bb91SDavid Härdeman u32 *scancode, u8 *toggle) 280cb7a01acSMauro Carvalho Chehab { 281cb7a01acSMauro Carvalho Chehab unsigned char subaddr, key, keygroup; 282cb7a01acSMauro Carvalho Chehab struct i2c_msg msg[] = { { .addr = ir->c->addr, .flags = 0, 283cb7a01acSMauro Carvalho Chehab .buf = &subaddr, .len = 1}, 284cb7a01acSMauro Carvalho Chehab { .addr = ir->c->addr, .flags = I2C_M_RD, 285cb7a01acSMauro Carvalho Chehab .buf = &key, .len = 1} }; 286cb7a01acSMauro Carvalho Chehab subaddr = 0x0d; 287cb7a01acSMauro Carvalho Chehab if (2 != i2c_transfer(ir->c->adapter, msg, 2)) { 28850a762b4SSean Young dev_dbg(&ir->rc->dev, "read error\n"); 289cb7a01acSMauro Carvalho Chehab return -EIO; 290cb7a01acSMauro Carvalho Chehab } 291cb7a01acSMauro Carvalho Chehab 292cb7a01acSMauro Carvalho Chehab if (key == 0xff) 293cb7a01acSMauro Carvalho Chehab return 0; 294cb7a01acSMauro Carvalho Chehab 295cb7a01acSMauro Carvalho Chehab subaddr = 0x0b; 296cb7a01acSMauro Carvalho Chehab msg[1].buf = &keygroup; 297cb7a01acSMauro Carvalho Chehab if (2 != i2c_transfer(ir->c->adapter, msg, 2)) { 29850a762b4SSean Young dev_dbg(&ir->rc->dev, "read error\n"); 299cb7a01acSMauro Carvalho Chehab return -EIO; 300cb7a01acSMauro Carvalho Chehab } 301cb7a01acSMauro Carvalho Chehab 302cb7a01acSMauro Carvalho Chehab if (keygroup == 0xff) 303cb7a01acSMauro Carvalho Chehab return 0; 304cb7a01acSMauro Carvalho Chehab 30550a762b4SSean Young dev_dbg(&ir->rc->dev, "read key 0x%02x/0x%02x\n", key, keygroup); 30634fe2784SOndrej Zary if (keygroup < 2 || keygroup > 4) { 30750a762b4SSean Young dev_warn(&ir->rc->dev, "warning: invalid key group 0x%02x for key 0x%02x\n", 308cb7a01acSMauro Carvalho Chehab keygroup, key); 309cb7a01acSMauro Carvalho Chehab } 310cb7a01acSMauro Carvalho Chehab key |= (keygroup & 1) << 6; 311cb7a01acSMauro Carvalho Chehab 3126d741bfeSSean Young *protocol = RC_PROTO_UNKNOWN; 3134dd9bb91SDavid Härdeman *scancode = key; 3144dd9bb91SDavid Härdeman if (ir->c->addr == 0x41) /* AVerMedia EM78P153 */ 3154dd9bb91SDavid Härdeman *scancode |= keygroup << 8; 3164dd9bb91SDavid Härdeman *toggle = 0; 317cb7a01acSMauro Carvalho Chehab return 1; 318cb7a01acSMauro Carvalho Chehab } 319cb7a01acSMauro Carvalho Chehab 320cb7a01acSMauro Carvalho Chehab /* ----------------------------------------------------------------------- */ 321cb7a01acSMauro Carvalho Chehab 322cb7a01acSMauro Carvalho Chehab static int ir_key_poll(struct IR_i2c *ir) 323cb7a01acSMauro Carvalho Chehab { 3246d741bfeSSean Young enum rc_proto protocol; 3254dd9bb91SDavid Härdeman u32 scancode; 3264dd9bb91SDavid Härdeman u8 toggle; 327cb7a01acSMauro Carvalho Chehab int rc; 328cb7a01acSMauro Carvalho Chehab 32950a762b4SSean Young dev_dbg(&ir->rc->dev, "%s\n", __func__); 3304dd9bb91SDavid Härdeman rc = ir->get_key(ir, &protocol, &scancode, &toggle); 331cb7a01acSMauro Carvalho Chehab if (rc < 0) { 33250a762b4SSean Young dev_warn(&ir->rc->dev, "error %d\n", rc); 333cb7a01acSMauro Carvalho Chehab return rc; 334cb7a01acSMauro Carvalho Chehab } 335cb7a01acSMauro Carvalho Chehab 336cb7a01acSMauro Carvalho Chehab if (rc) { 33750a762b4SSean Young dev_dbg(&ir->rc->dev, "%s: proto = 0x%04x, scancode = 0x%08x\n", 338120703f9SDavid Härdeman __func__, protocol, scancode); 339120703f9SDavid Härdeman rc_keydown(ir->rc, protocol, scancode, toggle); 340cb7a01acSMauro Carvalho Chehab } 341cb7a01acSMauro Carvalho Chehab return 0; 342cb7a01acSMauro Carvalho Chehab } 343cb7a01acSMauro Carvalho Chehab 344cb7a01acSMauro Carvalho Chehab static void ir_work(struct work_struct *work) 345cb7a01acSMauro Carvalho Chehab { 346cb7a01acSMauro Carvalho Chehab int rc; 347cb7a01acSMauro Carvalho Chehab struct IR_i2c *ir = container_of(work, struct IR_i2c, work.work); 348cb7a01acSMauro Carvalho Chehab 349acaa34bfSSean Young /* 350acaa34bfSSean Young * If the transmit code is holding the lock, skip polling for 351acaa34bfSSean Young * IR, we'll get it to it next time round 352acaa34bfSSean Young */ 353acaa34bfSSean Young if (mutex_trylock(&ir->lock)) { 354cb7a01acSMauro Carvalho Chehab rc = ir_key_poll(ir); 355acaa34bfSSean Young mutex_unlock(&ir->lock); 356cb7a01acSMauro Carvalho Chehab if (rc == -ENODEV) { 357cb7a01acSMauro Carvalho Chehab rc_unregister_device(ir->rc); 358cb7a01acSMauro Carvalho Chehab ir->rc = NULL; 359cb7a01acSMauro Carvalho Chehab return; 360cb7a01acSMauro Carvalho Chehab } 361acaa34bfSSean Young } 362cb7a01acSMauro Carvalho Chehab 363cb7a01acSMauro Carvalho Chehab schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling_interval)); 364cb7a01acSMauro Carvalho Chehab } 365cb7a01acSMauro Carvalho Chehab 366a6927d81SSean Young static int ir_open(struct rc_dev *dev) 367a6927d81SSean Young { 368a6927d81SSean Young struct IR_i2c *ir = dev->priv; 369a6927d81SSean Young 370a6927d81SSean Young schedule_delayed_work(&ir->work, 0); 371a6927d81SSean Young 372a6927d81SSean Young return 0; 373a6927d81SSean Young } 374a6927d81SSean Young 375a6927d81SSean Young static void ir_close(struct rc_dev *dev) 376a6927d81SSean Young { 377a6927d81SSean Young struct IR_i2c *ir = dev->priv; 378a6927d81SSean Young 379a6927d81SSean Young cancel_delayed_work_sync(&ir->work); 380a6927d81SSean Young } 381a6927d81SSean Young 382acaa34bfSSean Young /* Zilog Transmit Interface */ 383acaa34bfSSean Young #define XTAL_FREQ 18432000 384acaa34bfSSean Young 385acaa34bfSSean Young #define ZILOG_SEND 0x80 386acaa34bfSSean Young #define ZILOG_UIR_END 0x40 387acaa34bfSSean Young #define ZILOG_INIT_END 0x20 388acaa34bfSSean Young #define ZILOG_LIR_END 0x10 389acaa34bfSSean Young 390acaa34bfSSean Young #define ZILOG_STATUS_OK 0x80 391acaa34bfSSean Young #define ZILOG_STATUS_TX 0x40 392acaa34bfSSean Young #define ZILOG_STATUS_SET 0x20 393acaa34bfSSean Young 394acaa34bfSSean Young /* 395acaa34bfSSean Young * As you can see here, very few different lengths of pulse and space 396acaa34bfSSean Young * can be encoded. This means that the hardware does not work well with 397acaa34bfSSean Young * recorded IR. It's best to work with generated IR, like from ir-ctl or 398acaa34bfSSean Young * the in-kernel encoders. 399acaa34bfSSean Young */ 400acaa34bfSSean Young struct code_block { 401acaa34bfSSean Young u8 length; 402acaa34bfSSean Young u16 pulse[7]; /* not aligned */ 403acaa34bfSSean Young u8 carrier_pulse; 404acaa34bfSSean Young u8 carrier_space; 405acaa34bfSSean Young u16 space[8]; /* not aligned */ 406acaa34bfSSean Young u8 codes[61]; 407acaa34bfSSean Young u8 csum[2]; 408acaa34bfSSean Young } __packed; 409acaa34bfSSean Young 410acaa34bfSSean Young static int send_data_block(struct IR_i2c *ir, int cmd, 411acaa34bfSSean Young struct code_block *code_block) 412acaa34bfSSean Young { 413acaa34bfSSean Young int i, j, ret; 414acaa34bfSSean Young u8 buf[5], *p; 415acaa34bfSSean Young 416acaa34bfSSean Young p = &code_block->length; 417acaa34bfSSean Young for (i = 0; p < code_block->csum; i++) 418acaa34bfSSean Young code_block->csum[i & 1] ^= *p++; 419acaa34bfSSean Young 420acaa34bfSSean Young p = &code_block->length; 421acaa34bfSSean Young 422acaa34bfSSean Young for (i = 0; i < sizeof(*code_block);) { 423acaa34bfSSean Young int tosend = sizeof(*code_block) - i; 424acaa34bfSSean Young 425acaa34bfSSean Young if (tosend > 4) 426acaa34bfSSean Young tosend = 4; 427acaa34bfSSean Young buf[0] = i + 1; 428acaa34bfSSean Young for (j = 0; j < tosend; ++j) 429acaa34bfSSean Young buf[1 + j] = p[i + j]; 430acaa34bfSSean Young dev_dbg(&ir->rc->dev, "%*ph", tosend + 1, buf); 431acaa34bfSSean Young ret = i2c_master_send(ir->tx_c, buf, tosend + 1); 432acaa34bfSSean Young if (ret != tosend + 1) { 433acaa34bfSSean Young dev_dbg(&ir->rc->dev, 434acaa34bfSSean Young "i2c_master_send failed with %d\n", ret); 435acaa34bfSSean Young return ret < 0 ? ret : -EIO; 436acaa34bfSSean Young } 437acaa34bfSSean Young i += tosend; 438acaa34bfSSean Young } 439acaa34bfSSean Young 440acaa34bfSSean Young buf[0] = 0; 441acaa34bfSSean Young buf[1] = cmd; 442acaa34bfSSean Young ret = i2c_master_send(ir->tx_c, buf, 2); 443acaa34bfSSean Young if (ret != 2) { 444acaa34bfSSean Young dev_err(&ir->rc->dev, "i2c_master_send failed with %d\n", ret); 445acaa34bfSSean Young return ret < 0 ? ret : -EIO; 446acaa34bfSSean Young } 447acaa34bfSSean Young 448acaa34bfSSean Young usleep_range(2000, 5000); 449acaa34bfSSean Young 450acaa34bfSSean Young ret = i2c_master_send(ir->tx_c, buf, 1); 451acaa34bfSSean Young if (ret != 1) { 452acaa34bfSSean Young dev_err(&ir->rc->dev, "i2c_master_send failed with %d\n", ret); 453acaa34bfSSean Young return ret < 0 ? ret : -EIO; 454acaa34bfSSean Young } 455acaa34bfSSean Young 456acaa34bfSSean Young return 0; 457acaa34bfSSean Young } 458acaa34bfSSean Young 459acaa34bfSSean Young static int zilog_init(struct IR_i2c *ir) 460acaa34bfSSean Young { 461acaa34bfSSean Young struct code_block code_block = { .length = sizeof(code_block) }; 462acaa34bfSSean Young u8 buf[4]; 463acaa34bfSSean Young int ret; 464acaa34bfSSean Young 465acaa34bfSSean Young put_unaligned_be16(0x1000, &code_block.pulse[3]); 466acaa34bfSSean Young 467acaa34bfSSean Young ret = send_data_block(ir, ZILOG_INIT_END, &code_block); 468acaa34bfSSean Young if (ret) 469acaa34bfSSean Young return ret; 470acaa34bfSSean Young 471acaa34bfSSean Young ret = i2c_master_recv(ir->tx_c, buf, 4); 472acaa34bfSSean Young if (ret != 4) { 473acaa34bfSSean Young dev_err(&ir->c->dev, "failed to retrieve firmware version: %d\n", 474acaa34bfSSean Young ret); 475acaa34bfSSean Young return ret < 0 ? ret : -EIO; 476acaa34bfSSean Young } 477acaa34bfSSean Young 478acaa34bfSSean Young dev_info(&ir->c->dev, "Zilog/Hauppauge IR blaster firmware version %d.%d.%d\n", 479acaa34bfSSean Young buf[1], buf[2], buf[3]); 480acaa34bfSSean Young 481acaa34bfSSean Young return 0; 482acaa34bfSSean Young } 483acaa34bfSSean Young 484acaa34bfSSean Young /* 485acaa34bfSSean Young * If the last slot for pulse is the same as the current slot for pulse, 486acaa34bfSSean Young * then use slot no 7. 487acaa34bfSSean Young */ 488acaa34bfSSean Young static void copy_codes(u8 *dst, u8 *src, unsigned int count) 489acaa34bfSSean Young { 490acaa34bfSSean Young u8 c, last = 0xff; 491acaa34bfSSean Young 492acaa34bfSSean Young while (count--) { 493acaa34bfSSean Young c = *src++; 494acaa34bfSSean Young if ((c & 0xf0) == last) { 495acaa34bfSSean Young *dst++ = 0x70 | (c & 0xf); 496acaa34bfSSean Young } else { 497acaa34bfSSean Young *dst++ = c; 498acaa34bfSSean Young last = c & 0xf0; 499acaa34bfSSean Young } 500acaa34bfSSean Young } 501acaa34bfSSean Young } 502acaa34bfSSean Young 503acaa34bfSSean Young /* 504acaa34bfSSean Young * When looking for repeats, we don't care about the trailing space. This 505acaa34bfSSean Young * is set to the shortest possible anyway. 506acaa34bfSSean Young */ 507acaa34bfSSean Young static int cmp_no_trail(u8 *a, u8 *b, unsigned int count) 508acaa34bfSSean Young { 509acaa34bfSSean Young while (--count) { 510acaa34bfSSean Young if (*a++ != *b++) 511acaa34bfSSean Young return 1; 512acaa34bfSSean Young } 513acaa34bfSSean Young 514acaa34bfSSean Young return (*a & 0xf0) - (*b & 0xf0); 515acaa34bfSSean Young } 516acaa34bfSSean Young 517acaa34bfSSean Young static int find_slot(u16 *array, unsigned int size, u16 val) 518acaa34bfSSean Young { 519acaa34bfSSean Young int i; 520acaa34bfSSean Young 521acaa34bfSSean Young for (i = 0; i < size; i++) { 522acaa34bfSSean Young if (get_unaligned_be16(&array[i]) == val) { 523acaa34bfSSean Young return i; 524acaa34bfSSean Young } else if (!array[i]) { 525acaa34bfSSean Young put_unaligned_be16(val, &array[i]); 526acaa34bfSSean Young return i; 527acaa34bfSSean Young } 528acaa34bfSSean Young } 529acaa34bfSSean Young 530acaa34bfSSean Young return -1; 531acaa34bfSSean Young } 532acaa34bfSSean Young 533acaa34bfSSean Young static int zilog_ir_format(struct rc_dev *rcdev, unsigned int *txbuf, 534acaa34bfSSean Young unsigned int count, struct code_block *code_block) 535acaa34bfSSean Young { 536acaa34bfSSean Young struct IR_i2c *ir = rcdev->priv; 537acaa34bfSSean Young int rep, i, l, p = 0, s, c = 0; 538acaa34bfSSean Young bool repeating; 539acaa34bfSSean Young u8 codes[174]; 540acaa34bfSSean Young 541acaa34bfSSean Young code_block->carrier_pulse = DIV_ROUND_CLOSEST( 542acaa34bfSSean Young ir->duty_cycle * XTAL_FREQ / 1000, ir->carrier); 543acaa34bfSSean Young code_block->carrier_space = DIV_ROUND_CLOSEST( 544acaa34bfSSean Young (100 - ir->duty_cycle) * XTAL_FREQ / 1000, ir->carrier); 545acaa34bfSSean Young 546acaa34bfSSean Young for (i = 0; i < count; i++) { 547acaa34bfSSean Young if (c >= ARRAY_SIZE(codes) - 1) { 548acaa34bfSSean Young dev_warn(&rcdev->dev, "IR too long, cannot transmit\n"); 549acaa34bfSSean Young return -EINVAL; 550acaa34bfSSean Young } 551acaa34bfSSean Young 552acaa34bfSSean Young /* 553acaa34bfSSean Young * Lengths more than 142220us cannot be encoded; also 554acaa34bfSSean Young * this checks for multiply overflow 555acaa34bfSSean Young */ 556acaa34bfSSean Young if (txbuf[i] > 142220) 557acaa34bfSSean Young return -EINVAL; 558acaa34bfSSean Young 559acaa34bfSSean Young l = DIV_ROUND_CLOSEST((XTAL_FREQ / 1000) * txbuf[i], 40000); 560acaa34bfSSean Young 561acaa34bfSSean Young if (i & 1) { 562acaa34bfSSean Young s = find_slot(code_block->space, 563acaa34bfSSean Young ARRAY_SIZE(code_block->space), l); 564acaa34bfSSean Young if (s == -1) { 565acaa34bfSSean Young dev_warn(&rcdev->dev, "Too many different lengths spaces, cannot transmit"); 566acaa34bfSSean Young return -EINVAL; 567acaa34bfSSean Young } 568acaa34bfSSean Young 569acaa34bfSSean Young /* We have a pulse and space */ 570acaa34bfSSean Young codes[c++] = (p << 4) | s; 571acaa34bfSSean Young } else { 572acaa34bfSSean Young p = find_slot(code_block->pulse, 573acaa34bfSSean Young ARRAY_SIZE(code_block->pulse), l); 574acaa34bfSSean Young if (p == -1) { 575acaa34bfSSean Young dev_warn(&rcdev->dev, "Too many different lengths pulses, cannot transmit"); 576acaa34bfSSean Young return -EINVAL; 577acaa34bfSSean Young } 578acaa34bfSSean Young } 579acaa34bfSSean Young } 580acaa34bfSSean Young 581acaa34bfSSean Young /* We have to encode the trailing pulse. Find the shortest space */ 582acaa34bfSSean Young s = 0; 583acaa34bfSSean Young for (i = 1; i < ARRAY_SIZE(code_block->space); i++) { 584acaa34bfSSean Young u16 d = get_unaligned_be16(&code_block->space[i]); 585acaa34bfSSean Young 586acaa34bfSSean Young if (get_unaligned_be16(&code_block->space[s]) > d) 587acaa34bfSSean Young s = i; 588acaa34bfSSean Young } 589acaa34bfSSean Young 590acaa34bfSSean Young codes[c++] = (p << 4) | s; 591acaa34bfSSean Young 592acaa34bfSSean Young dev_dbg(&rcdev->dev, "generated %d codes\n", c); 593acaa34bfSSean Young 594acaa34bfSSean Young /* 595acaa34bfSSean Young * Are the last N codes (so pulse + space) repeating 3 times? 596acaa34bfSSean Young * if so we can shorten the codes list and use code 0xc0 to repeat 597acaa34bfSSean Young * them. 598acaa34bfSSean Young */ 599acaa34bfSSean Young repeating = false; 600acaa34bfSSean Young 601acaa34bfSSean Young for (rep = c / 3; rep >= 1; rep--) { 602acaa34bfSSean Young if (!memcmp(&codes[c - rep * 3], &codes[c - rep * 2], rep) && 603acaa34bfSSean Young !cmp_no_trail(&codes[c - rep], &codes[c - rep * 2], rep)) { 604acaa34bfSSean Young repeating = true; 605acaa34bfSSean Young break; 606acaa34bfSSean Young } 607acaa34bfSSean Young } 608acaa34bfSSean Young 609acaa34bfSSean Young if (repeating) { 610acaa34bfSSean Young /* first copy any leading non-repeating */ 611acaa34bfSSean Young int leading = c - rep * 3; 612acaa34bfSSean Young 6139863bc49SMauro Carvalho Chehab if (leading >= ARRAY_SIZE(code_block->codes) - 3 - rep) { 614acaa34bfSSean Young dev_warn(&rcdev->dev, "IR too long, cannot transmit\n"); 615acaa34bfSSean Young return -EINVAL; 616acaa34bfSSean Young } 617acaa34bfSSean Young 618acaa34bfSSean Young dev_dbg(&rcdev->dev, "found trailing %d repeat\n", rep); 619acaa34bfSSean Young copy_codes(code_block->codes, codes, leading); 620acaa34bfSSean Young code_block->codes[leading] = 0x82; 621acaa34bfSSean Young copy_codes(code_block->codes + leading + 1, codes + leading, 622acaa34bfSSean Young rep); 623acaa34bfSSean Young c = leading + 1 + rep; 624acaa34bfSSean Young code_block->codes[c++] = 0xc0; 625acaa34bfSSean Young } else { 626acaa34bfSSean Young if (c >= ARRAY_SIZE(code_block->codes) - 3) { 627acaa34bfSSean Young dev_warn(&rcdev->dev, "IR too long, cannot transmit\n"); 628acaa34bfSSean Young return -EINVAL; 629acaa34bfSSean Young } 630acaa34bfSSean Young 631acaa34bfSSean Young dev_dbg(&rcdev->dev, "found no trailing repeat\n"); 632acaa34bfSSean Young code_block->codes[0] = 0x82; 633acaa34bfSSean Young copy_codes(code_block->codes + 1, codes, c); 634acaa34bfSSean Young c++; 635acaa34bfSSean Young code_block->codes[c++] = 0xc4; 636acaa34bfSSean Young } 637acaa34bfSSean Young 638acaa34bfSSean Young while (c < ARRAY_SIZE(code_block->codes)) 639acaa34bfSSean Young code_block->codes[c++] = 0x83; 640acaa34bfSSean Young 641acaa34bfSSean Young return 0; 642acaa34bfSSean Young } 643acaa34bfSSean Young 644acaa34bfSSean Young static int zilog_tx(struct rc_dev *rcdev, unsigned int *txbuf, 645acaa34bfSSean Young unsigned int count) 646acaa34bfSSean Young { 647acaa34bfSSean Young struct IR_i2c *ir = rcdev->priv; 648acaa34bfSSean Young struct code_block code_block = { .length = sizeof(code_block) }; 649acaa34bfSSean Young u8 buf[2]; 650acaa34bfSSean Young int ret, i; 651acaa34bfSSean Young 652acaa34bfSSean Young ret = zilog_ir_format(rcdev, txbuf, count, &code_block); 653acaa34bfSSean Young if (ret) 654acaa34bfSSean Young return ret; 655acaa34bfSSean Young 656acaa34bfSSean Young ret = mutex_lock_interruptible(&ir->lock); 657acaa34bfSSean Young if (ret) 658acaa34bfSSean Young return ret; 659acaa34bfSSean Young 660acaa34bfSSean Young ret = send_data_block(ir, ZILOG_UIR_END, &code_block); 661acaa34bfSSean Young if (ret) 662acaa34bfSSean Young goto out_unlock; 663acaa34bfSSean Young 664acaa34bfSSean Young ret = i2c_master_recv(ir->tx_c, buf, 1); 665acaa34bfSSean Young if (ret != 1) { 666acaa34bfSSean Young dev_err(&ir->rc->dev, "i2c_master_recv failed with %d\n", ret); 667acaa34bfSSean Young goto out_unlock; 668acaa34bfSSean Young } 669acaa34bfSSean Young 670acaa34bfSSean Young dev_dbg(&ir->rc->dev, "code set status: %02x\n", buf[0]); 671acaa34bfSSean Young 672acaa34bfSSean Young if (buf[0] != (ZILOG_STATUS_OK | ZILOG_STATUS_SET)) { 673acaa34bfSSean Young dev_err(&ir->rc->dev, "unexpected IR TX response %02x\n", 674acaa34bfSSean Young buf[0]); 675acaa34bfSSean Young ret = -EIO; 676acaa34bfSSean Young goto out_unlock; 677acaa34bfSSean Young } 678acaa34bfSSean Young 679acaa34bfSSean Young buf[0] = 0x00; 680acaa34bfSSean Young buf[1] = ZILOG_SEND; 681acaa34bfSSean Young 682acaa34bfSSean Young ret = i2c_master_send(ir->tx_c, buf, 2); 683acaa34bfSSean Young if (ret != 2) { 684acaa34bfSSean Young dev_err(&ir->rc->dev, "i2c_master_send failed with %d\n", ret); 685acaa34bfSSean Young if (ret >= 0) 686acaa34bfSSean Young ret = -EIO; 687acaa34bfSSean Young goto out_unlock; 688acaa34bfSSean Young } 689acaa34bfSSean Young 690acaa34bfSSean Young dev_dbg(&ir->rc->dev, "send command sent\n"); 691acaa34bfSSean Young 692acaa34bfSSean Young /* 693acaa34bfSSean Young * This bit NAKs until the device is ready, so we retry it 694acaa34bfSSean Young * sleeping a bit each time. This seems to be what the windows 695acaa34bfSSean Young * driver does, approximately. 696acaa34bfSSean Young * Try for up to 1s. 697acaa34bfSSean Young */ 698acaa34bfSSean Young for (i = 0; i < 20; ++i) { 699acaa34bfSSean Young set_current_state(TASK_UNINTERRUPTIBLE); 700acaa34bfSSean Young schedule_timeout(msecs_to_jiffies(50)); 701acaa34bfSSean Young ret = i2c_master_send(ir->tx_c, buf, 1); 702acaa34bfSSean Young if (ret == 1) 703acaa34bfSSean Young break; 704acaa34bfSSean Young dev_dbg(&ir->rc->dev, 705acaa34bfSSean Young "NAK expected: i2c_master_send failed with %d (try %d)\n", 706acaa34bfSSean Young ret, i + 1); 707acaa34bfSSean Young } 708acaa34bfSSean Young 709acaa34bfSSean Young if (ret != 1) { 710acaa34bfSSean Young dev_err(&ir->rc->dev, 711acaa34bfSSean Young "IR TX chip never got ready: last i2c_master_send failed with %d\n", 712acaa34bfSSean Young ret); 713acaa34bfSSean Young if (ret >= 0) 714acaa34bfSSean Young ret = -EIO; 715acaa34bfSSean Young goto out_unlock; 716acaa34bfSSean Young } 717acaa34bfSSean Young 7189c87ae1aSChristophe JAILLET ret = i2c_master_recv(ir->tx_c, buf, 1); 7199c87ae1aSChristophe JAILLET if (ret != 1) { 720acaa34bfSSean Young dev_err(&ir->rc->dev, "i2c_master_recv failed with %d\n", ret); 721acaa34bfSSean Young ret = -EIO; 722acaa34bfSSean Young goto out_unlock; 723acaa34bfSSean Young } else if (buf[0] != ZILOG_STATUS_OK) { 724acaa34bfSSean Young dev_err(&ir->rc->dev, "unexpected IR TX response #2: %02x\n", 725acaa34bfSSean Young buf[0]); 726acaa34bfSSean Young ret = -EIO; 727acaa34bfSSean Young goto out_unlock; 728acaa34bfSSean Young } 729acaa34bfSSean Young dev_dbg(&ir->rc->dev, "transmit complete\n"); 730acaa34bfSSean Young 731acaa34bfSSean Young /* Oh good, it worked */ 732acaa34bfSSean Young ret = count; 733acaa34bfSSean Young out_unlock: 734acaa34bfSSean Young mutex_unlock(&ir->lock); 735acaa34bfSSean Young 736acaa34bfSSean Young return ret; 737acaa34bfSSean Young } 738acaa34bfSSean Young 739acaa34bfSSean Young static int zilog_tx_carrier(struct rc_dev *dev, u32 carrier) 740acaa34bfSSean Young { 741acaa34bfSSean Young struct IR_i2c *ir = dev->priv; 742acaa34bfSSean Young 743acaa34bfSSean Young if (carrier > 500000 || carrier < 20000) 744acaa34bfSSean Young return -EINVAL; 745acaa34bfSSean Young 746acaa34bfSSean Young ir->carrier = carrier; 747acaa34bfSSean Young 748acaa34bfSSean Young return 0; 749acaa34bfSSean Young } 750acaa34bfSSean Young 751acaa34bfSSean Young static int zilog_tx_duty_cycle(struct rc_dev *dev, u32 duty_cycle) 752acaa34bfSSean Young { 753acaa34bfSSean Young struct IR_i2c *ir = dev->priv; 754acaa34bfSSean Young 755acaa34bfSSean Young ir->duty_cycle = duty_cycle; 756acaa34bfSSean Young 757acaa34bfSSean Young return 0; 758acaa34bfSSean Young } 759cb7a01acSMauro Carvalho Chehab 760*135e0f3dSUwe Kleine-König static int ir_probe(struct i2c_client *client) 761cb7a01acSMauro Carvalho Chehab { 762*135e0f3dSUwe Kleine-König const struct i2c_device_id *id = i2c_client_get_device_id(client); 763cb7a01acSMauro Carvalho Chehab char *ir_codes = NULL; 764cb7a01acSMauro Carvalho Chehab const char *name = NULL; 7656d741bfeSSean Young u64 rc_proto = RC_PROTO_BIT_UNKNOWN; 766cb7a01acSMauro Carvalho Chehab struct IR_i2c *ir; 767cb7a01acSMauro Carvalho Chehab struct rc_dev *rc = NULL; 768cb7a01acSMauro Carvalho Chehab struct i2c_adapter *adap = client->adapter; 769cb7a01acSMauro Carvalho Chehab unsigned short addr = client->addr; 7707bc8a0deSSean Young bool probe_tx = (id->driver_data & FLAG_TX) != 0; 771cb7a01acSMauro Carvalho Chehab int err; 772cb7a01acSMauro Carvalho Chehab 7731cb26030SSean Young if ((id->driver_data & FLAG_HDPVR) && !enable_hdpvr) { 7741cb26030SSean Young dev_err(&client->dev, "IR for HDPVR is known to cause problems during recording, use enable_hdpvr modparam to enable\n"); 7751cb26030SSean Young return -ENODEV; 7761cb26030SSean Young } 7771cb26030SSean Young 778c02b211dSLaurent Pinchart ir = devm_kzalloc(&client->dev, sizeof(*ir), GFP_KERNEL); 779cb7a01acSMauro Carvalho Chehab if (!ir) 780cb7a01acSMauro Carvalho Chehab return -ENOMEM; 781cb7a01acSMauro Carvalho Chehab 782cb7a01acSMauro Carvalho Chehab ir->c = client; 783cb7a01acSMauro Carvalho Chehab ir->polling_interval = DEFAULT_POLLING_INTERVAL; 784cb7a01acSMauro Carvalho Chehab i2c_set_clientdata(client, ir); 785cb7a01acSMauro Carvalho Chehab 786cb7a01acSMauro Carvalho Chehab switch(addr) { 787cb7a01acSMauro Carvalho Chehab case 0x64: 788cb7a01acSMauro Carvalho Chehab name = "Pixelview"; 789cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_pixelview; 7906d741bfeSSean Young rc_proto = RC_PROTO_BIT_OTHER; 791cb7a01acSMauro Carvalho Chehab ir_codes = RC_MAP_EMPTY; 792cb7a01acSMauro Carvalho Chehab break; 793cb7a01acSMauro Carvalho Chehab case 0x18: 794cb7a01acSMauro Carvalho Chehab case 0x1f: 795cb7a01acSMauro Carvalho Chehab case 0x1a: 796cb7a01acSMauro Carvalho Chehab name = "Hauppauge"; 797cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_haup; 7986d741bfeSSean Young rc_proto = RC_PROTO_BIT_RC5; 799cb7a01acSMauro Carvalho Chehab ir_codes = RC_MAP_HAUPPAUGE; 800cb7a01acSMauro Carvalho Chehab break; 801cb7a01acSMauro Carvalho Chehab case 0x30: 802cb7a01acSMauro Carvalho Chehab name = "KNC One"; 803cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_knc1; 8046d741bfeSSean Young rc_proto = RC_PROTO_BIT_OTHER; 805cb7a01acSMauro Carvalho Chehab ir_codes = RC_MAP_EMPTY; 806cb7a01acSMauro Carvalho Chehab break; 80739dfd52dSDaniel González Cabanelas case 0x33: 80839dfd52dSDaniel González Cabanelas name = "Geniatech"; 80939dfd52dSDaniel González Cabanelas ir->get_key = get_key_geniatech; 81039dfd52dSDaniel González Cabanelas rc_proto = RC_PROTO_BIT_RC5; 81139dfd52dSDaniel González Cabanelas ir_codes = RC_MAP_TOTAL_MEDIA_IN_HAND_02; 81239dfd52dSDaniel González Cabanelas ir->old = 0xfc; 81339dfd52dSDaniel González Cabanelas break; 814cb7a01acSMauro Carvalho Chehab case 0x6b: 815cb7a01acSMauro Carvalho Chehab name = "FusionHDTV"; 816cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_fusionhdtv; 8176d741bfeSSean Young rc_proto = RC_PROTO_BIT_UNKNOWN; 818cb7a01acSMauro Carvalho Chehab ir_codes = RC_MAP_FUSIONHDTV_MCE; 819cb7a01acSMauro Carvalho Chehab break; 820cb7a01acSMauro Carvalho Chehab case 0x40: 821cb7a01acSMauro Carvalho Chehab name = "AVerMedia Cardbus remote"; 822cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_avermedia_cardbus; 8236d741bfeSSean Young rc_proto = RC_PROTO_BIT_OTHER; 824cb7a01acSMauro Carvalho Chehab ir_codes = RC_MAP_AVERMEDIA_CARDBUS; 825cb7a01acSMauro Carvalho Chehab break; 82634fe2784SOndrej Zary case 0x41: 82734fe2784SOndrej Zary name = "AVerMedia EM78P153"; 82834fe2784SOndrej Zary ir->get_key = get_key_avermedia_cardbus; 8296d741bfeSSean Young rc_proto = RC_PROTO_BIT_OTHER; 83034fe2784SOndrej Zary /* RM-KV remote, seems to be same as RM-K6 */ 83134fe2784SOndrej Zary ir_codes = RC_MAP_AVERMEDIA_M733A_RM_K6; 83234fe2784SOndrej Zary break; 833cb7a01acSMauro Carvalho Chehab case 0x71: 834cb7a01acSMauro Carvalho Chehab name = "Hauppauge/Zilog Z8"; 835cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_haup_xvr; 8366d741bfeSSean Young rc_proto = RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC6_MCE | 8376d741bfeSSean Young RC_PROTO_BIT_RC6_6A_32; 838cb7a01acSMauro Carvalho Chehab ir_codes = RC_MAP_HAUPPAUGE; 839c73ba202SSean Young ir->polling_interval = 125; 8407bc8a0deSSean Young probe_tx = true; 841cb7a01acSMauro Carvalho Chehab break; 842cb7a01acSMauro Carvalho Chehab } 843cb7a01acSMauro Carvalho Chehab 844cb7a01acSMauro Carvalho Chehab /* Let the caller override settings */ 845cb7a01acSMauro Carvalho Chehab if (client->dev.platform_data) { 846cb7a01acSMauro Carvalho Chehab const struct IR_i2c_init_data *init_data = 847cb7a01acSMauro Carvalho Chehab client->dev.platform_data; 848cb7a01acSMauro Carvalho Chehab 849cb7a01acSMauro Carvalho Chehab ir_codes = init_data->ir_codes; 850cb7a01acSMauro Carvalho Chehab rc = init_data->rc_dev; 851cb7a01acSMauro Carvalho Chehab 852cb7a01acSMauro Carvalho Chehab name = init_data->name; 853cb7a01acSMauro Carvalho Chehab if (init_data->type) 8546d741bfeSSean Young rc_proto = init_data->type; 855cb7a01acSMauro Carvalho Chehab 856cb7a01acSMauro Carvalho Chehab if (init_data->polling_interval) 857cb7a01acSMauro Carvalho Chehab ir->polling_interval = init_data->polling_interval; 858cb7a01acSMauro Carvalho Chehab 859cb7a01acSMauro Carvalho Chehab switch (init_data->internal_get_key_func) { 860cb7a01acSMauro Carvalho Chehab case IR_KBD_GET_KEY_CUSTOM: 861cb7a01acSMauro Carvalho Chehab /* The bridge driver provided us its own function */ 862cb7a01acSMauro Carvalho Chehab ir->get_key = init_data->get_key; 863cb7a01acSMauro Carvalho Chehab break; 864cb7a01acSMauro Carvalho Chehab case IR_KBD_GET_KEY_PIXELVIEW: 865cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_pixelview; 866cb7a01acSMauro Carvalho Chehab break; 867cb7a01acSMauro Carvalho Chehab case IR_KBD_GET_KEY_HAUP: 868cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_haup; 869cb7a01acSMauro Carvalho Chehab break; 870cb7a01acSMauro Carvalho Chehab case IR_KBD_GET_KEY_KNC1: 871cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_knc1; 872cb7a01acSMauro Carvalho Chehab break; 87339dfd52dSDaniel González Cabanelas case IR_KBD_GET_KEY_GENIATECH: 87439dfd52dSDaniel González Cabanelas ir->get_key = get_key_geniatech; 87539dfd52dSDaniel González Cabanelas break; 876cb7a01acSMauro Carvalho Chehab case IR_KBD_GET_KEY_FUSIONHDTV: 877cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_fusionhdtv; 878cb7a01acSMauro Carvalho Chehab break; 879cb7a01acSMauro Carvalho Chehab case IR_KBD_GET_KEY_HAUP_XVR: 880cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_haup_xvr; 881cb7a01acSMauro Carvalho Chehab break; 882cb7a01acSMauro Carvalho Chehab case IR_KBD_GET_KEY_AVERMEDIA_CARDBUS: 883cb7a01acSMauro Carvalho Chehab ir->get_key = get_key_avermedia_cardbus; 884cb7a01acSMauro Carvalho Chehab break; 885cb7a01acSMauro Carvalho Chehab } 886cb7a01acSMauro Carvalho Chehab } 887cb7a01acSMauro Carvalho Chehab 888cb7a01acSMauro Carvalho Chehab if (!rc) { 889cb7a01acSMauro Carvalho Chehab /* 89039c1cb2bSJonathan McCrohan * If platform_data doesn't specify rc_dev, initialize it 891cb7a01acSMauro Carvalho Chehab * internally 892cb7a01acSMauro Carvalho Chehab */ 8930f7499fdSAndi Shyti rc = rc_allocate_device(RC_DRIVER_SCANCODE); 894c02b211dSLaurent Pinchart if (!rc) 895c02b211dSLaurent Pinchart return -ENOMEM; 896cb7a01acSMauro Carvalho Chehab } 897cb7a01acSMauro Carvalho Chehab ir->rc = rc; 898cb7a01acSMauro Carvalho Chehab 899cb7a01acSMauro Carvalho Chehab /* Make sure we are all setup before going on */ 9006d741bfeSSean Young if (!name || !ir->get_key || !rc_proto || !ir_codes) { 90150a762b4SSean Young dev_warn(&client->dev, "Unsupported device at address 0x%02x\n", 902cb7a01acSMauro Carvalho Chehab addr); 903cb7a01acSMauro Carvalho Chehab err = -ENODEV; 904cb7a01acSMauro Carvalho Chehab goto err_out_free; 905cb7a01acSMauro Carvalho Chehab } 906cb7a01acSMauro Carvalho Chehab 907cb7a01acSMauro Carvalho Chehab ir->ir_codes = ir_codes; 908cb7a01acSMauro Carvalho Chehab 909afc7f24cSSean Young snprintf(ir->phys, sizeof(ir->phys), "%s/%s", dev_name(&adap->dev), 910cb7a01acSMauro Carvalho Chehab dev_name(&client->dev)); 911cb7a01acSMauro Carvalho Chehab 912cb7a01acSMauro Carvalho Chehab /* 913cb7a01acSMauro Carvalho Chehab * Initialize input_dev fields 914cb7a01acSMauro Carvalho Chehab * It doesn't make sense to allow overriding them via platform_data 915cb7a01acSMauro Carvalho Chehab */ 916cb7a01acSMauro Carvalho Chehab rc->input_id.bustype = BUS_I2C; 917cb7a01acSMauro Carvalho Chehab rc->input_phys = ir->phys; 918afc7f24cSSean Young rc->device_name = name; 919afc7f24cSSean Young rc->dev.parent = &client->dev; 920a6927d81SSean Young rc->priv = ir; 921a6927d81SSean Young rc->open = ir_open; 922a6927d81SSean Young rc->close = ir_close; 923cb7a01acSMauro Carvalho Chehab 924cb7a01acSMauro Carvalho Chehab /* 925cb7a01acSMauro Carvalho Chehab * Initialize the other fields of rc_dev 926cb7a01acSMauro Carvalho Chehab */ 927cb7a01acSMauro Carvalho Chehab rc->map_name = ir->ir_codes; 9286d741bfeSSean Young rc->allowed_protocols = rc_proto; 929cb7a01acSMauro Carvalho Chehab if (!rc->driver_name) 93050a762b4SSean Young rc->driver_name = KBUILD_MODNAME; 931cb7a01acSMauro Carvalho Chehab 932acaa34bfSSean Young mutex_init(&ir->lock); 933acaa34bfSSean Young 934a6927d81SSean Young INIT_DELAYED_WORK(&ir->work, ir_work); 935a6927d81SSean Young 9367bc8a0deSSean Young if (probe_tx) { 9371b09a2afSWolfram Sang ir->tx_c = i2c_new_dummy_device(client->adapter, 0x70); 9381b09a2afSWolfram Sang if (IS_ERR(ir->tx_c)) { 939acaa34bfSSean Young dev_err(&client->dev, "failed to setup tx i2c address"); 9401b09a2afSWolfram Sang err = PTR_ERR(ir->tx_c); 9411b09a2afSWolfram Sang goto err_out_free; 942acaa34bfSSean Young } else if (!zilog_init(ir)) { 943acaa34bfSSean Young ir->carrier = 38000; 944acaa34bfSSean Young ir->duty_cycle = 40; 945acaa34bfSSean Young rc->tx_ir = zilog_tx; 946acaa34bfSSean Young rc->s_tx_carrier = zilog_tx_carrier; 947acaa34bfSSean Young rc->s_tx_duty_cycle = zilog_tx_duty_cycle; 948acaa34bfSSean Young } 949acaa34bfSSean Young } 950acaa34bfSSean Young 951cb7a01acSMauro Carvalho Chehab err = rc_register_device(rc); 952cb7a01acSMauro Carvalho Chehab if (err) 953cb7a01acSMauro Carvalho Chehab goto err_out_free; 954cb7a01acSMauro Carvalho Chehab 955cb7a01acSMauro Carvalho Chehab return 0; 956cb7a01acSMauro Carvalho Chehab 957cb7a01acSMauro Carvalho Chehab err_out_free: 9581b09a2afSWolfram Sang if (!IS_ERR(ir->tx_c)) 959acaa34bfSSean Young i2c_unregister_device(ir->tx_c); 960acaa34bfSSean Young 961cb7a01acSMauro Carvalho Chehab /* Only frees rc if it were allocated internally */ 962cb7a01acSMauro Carvalho Chehab rc_free_device(rc); 963cb7a01acSMauro Carvalho Chehab return err; 964cb7a01acSMauro Carvalho Chehab } 965cb7a01acSMauro Carvalho Chehab 966ed5c2f5fSUwe Kleine-König static void ir_remove(struct i2c_client *client) 967cb7a01acSMauro Carvalho Chehab { 968cb7a01acSMauro Carvalho Chehab struct IR_i2c *ir = i2c_get_clientdata(client); 969cb7a01acSMauro Carvalho Chehab 970cb7a01acSMauro Carvalho Chehab cancel_delayed_work_sync(&ir->work); 971cb7a01acSMauro Carvalho Chehab 972acaa34bfSSean Young i2c_unregister_device(ir->tx_c); 973acaa34bfSSean Young 974cb7a01acSMauro Carvalho Chehab rc_unregister_device(ir->rc); 975cb7a01acSMauro Carvalho Chehab } 976cb7a01acSMauro Carvalho Chehab 977cb7a01acSMauro Carvalho Chehab static const struct i2c_device_id ir_kbd_id[] = { 978cb7a01acSMauro Carvalho Chehab /* Generic entry for any IR receiver */ 979cb7a01acSMauro Carvalho Chehab { "ir_video", 0 }, 980cb7a01acSMauro Carvalho Chehab /* IR device specific entries should be added here */ 981acaa34bfSSean Young { "ir_z8f0811_haup", FLAG_TX }, 982acaa34bfSSean Young { "ir_z8f0811_hdpvr", FLAG_TX | FLAG_HDPVR }, 983cb7a01acSMauro Carvalho Chehab { } 984cb7a01acSMauro Carvalho Chehab }; 9851cb26030SSean Young MODULE_DEVICE_TABLE(i2c, ir_kbd_id); 986cb7a01acSMauro Carvalho Chehab 987cb7a01acSMauro Carvalho Chehab static struct i2c_driver ir_kbd_driver = { 988cb7a01acSMauro Carvalho Chehab .driver = { 989cb7a01acSMauro Carvalho Chehab .name = "ir-kbd-i2c", 990cb7a01acSMauro Carvalho Chehab }, 991*135e0f3dSUwe Kleine-König .probe_new = ir_probe, 992cb7a01acSMauro Carvalho Chehab .remove = ir_remove, 993cb7a01acSMauro Carvalho Chehab .id_table = ir_kbd_id, 994cb7a01acSMauro Carvalho Chehab }; 995cb7a01acSMauro Carvalho Chehab 996cb7a01acSMauro Carvalho Chehab module_i2c_driver(ir_kbd_driver); 997cb7a01acSMauro Carvalho Chehab 998cb7a01acSMauro Carvalho Chehab /* ----------------------------------------------------------------------- */ 999cb7a01acSMauro Carvalho Chehab 1000cb7a01acSMauro Carvalho Chehab MODULE_AUTHOR("Gerd Knorr, Michal Kochanowicz, Christoph Bartelmus, Ulrich Mueller"); 1001cb7a01acSMauro Carvalho Chehab MODULE_DESCRIPTION("input driver for i2c IR remote controls"); 1002cb7a01acSMauro Carvalho Chehab MODULE_LICENSE("GPL"); 1003