1b285192aSMauro Carvalho Chehab /* 2b285192aSMauro Carvalho Chehab * 3b285192aSMauro Carvalho Chehab * handle saa7134 IR remotes via linux kernel input layer. 4b285192aSMauro Carvalho Chehab * 5b285192aSMauro Carvalho Chehab * This program is free software; you can redistribute it and/or modify 6b285192aSMauro Carvalho Chehab * it under the terms of the GNU General Public License as published by 7b285192aSMauro Carvalho Chehab * the Free Software Foundation; either version 2 of the License, or 8b285192aSMauro Carvalho Chehab * (at your option) any later version. 9b285192aSMauro Carvalho Chehab * 10b285192aSMauro Carvalho Chehab * This program is distributed in the hope that it will be useful, 11b285192aSMauro Carvalho Chehab * but WITHOUT ANY WARRANTY; without even the implied warranty of 12b285192aSMauro Carvalho Chehab * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13b285192aSMauro Carvalho Chehab * GNU General Public License for more details. 14b285192aSMauro Carvalho Chehab * 15b285192aSMauro Carvalho Chehab * You should have received a copy of the GNU General Public License 16b285192aSMauro Carvalho Chehab * along with this program; if not, write to the Free Software 17b285192aSMauro Carvalho Chehab * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18b285192aSMauro Carvalho Chehab * 19b285192aSMauro Carvalho Chehab */ 20b285192aSMauro Carvalho Chehab 219a12ccfcSMauro Carvalho Chehab #include "saa7134.h" 229a12ccfcSMauro Carvalho Chehab #include "saa7134-reg.h" 239a12ccfcSMauro Carvalho Chehab 24b285192aSMauro Carvalho Chehab #include <linux/module.h> 25b285192aSMauro Carvalho Chehab #include <linux/init.h> 26b285192aSMauro Carvalho Chehab #include <linux/delay.h> 27b285192aSMauro Carvalho Chehab #include <linux/interrupt.h> 28b285192aSMauro Carvalho Chehab #include <linux/slab.h> 29b285192aSMauro Carvalho Chehab 30b285192aSMauro Carvalho Chehab #define MODULE_NAME "saa7134" 31b285192aSMauro Carvalho Chehab 32b285192aSMauro Carvalho Chehab static unsigned int disable_ir; 33b285192aSMauro Carvalho Chehab module_param(disable_ir, int, 0444); 34b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(disable_ir,"disable infrared remote support"); 35b285192aSMauro Carvalho Chehab 36b285192aSMauro Carvalho Chehab static unsigned int ir_debug; 37b285192aSMauro Carvalho Chehab module_param(ir_debug, int, 0644); 38b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]"); 39b285192aSMauro Carvalho Chehab 40b285192aSMauro Carvalho Chehab static int pinnacle_remote; 41b285192aSMauro Carvalho Chehab module_param(pinnacle_remote, int, 0644); /* Choose Pinnacle PCTV remote */ 42b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(pinnacle_remote, "Specify Pinnacle PCTV remote: 0=coloured, 1=grey (defaults to 0)"); 43b285192aSMauro Carvalho Chehab 4445f38cb3SMauro Carvalho Chehab #define input_dbg(fmt, arg...) do { \ 4545f38cb3SMauro Carvalho Chehab if (ir_debug) \ 4645f38cb3SMauro Carvalho Chehab printk(KERN_DEBUG pr_fmt("input: " fmt), ## arg); \ 4745f38cb3SMauro Carvalho Chehab } while (0) 4845f38cb3SMauro Carvalho Chehab #define ir_dbg(ir, fmt, arg...) do { \ 4945f38cb3SMauro Carvalho Chehab if (ir_debug) \ 5045f38cb3SMauro Carvalho Chehab printk(KERN_DEBUG pr_fmt("ir %s: " fmt), ir->name, ## arg); \ 5145f38cb3SMauro Carvalho Chehab } while (0) 52b285192aSMauro Carvalho Chehab 53b285192aSMauro Carvalho Chehab /* Helper function for raw decoding at GPIO16 or GPIO18 */ 54b285192aSMauro Carvalho Chehab static int saa7134_raw_decode_irq(struct saa7134_dev *dev); 55b285192aSMauro Carvalho Chehab 56b285192aSMauro Carvalho Chehab /* -------------------- GPIO generic keycode builder -------------------- */ 57b285192aSMauro Carvalho Chehab 58b285192aSMauro Carvalho Chehab static int build_key(struct saa7134_dev *dev) 59b285192aSMauro Carvalho Chehab { 60b285192aSMauro Carvalho Chehab struct saa7134_card_ir *ir = dev->remote; 61b285192aSMauro Carvalho Chehab u32 gpio, data; 62b285192aSMauro Carvalho Chehab 63b285192aSMauro Carvalho Chehab /* here comes the additional handshake steps for some cards */ 64b285192aSMauro Carvalho Chehab switch (dev->board) { 65b285192aSMauro Carvalho Chehab case SAA7134_BOARD_GOTVIEW_7135: 66b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPSTATUS1, 0x80); 67b285192aSMauro Carvalho Chehab saa_clearb(SAA7134_GPIO_GPSTATUS1, 0x80); 68b285192aSMauro Carvalho Chehab break; 69b285192aSMauro Carvalho Chehab } 70b285192aSMauro Carvalho Chehab /* rising SAA7134_GPIO_GPRESCAN reads the status */ 71b285192aSMauro Carvalho Chehab saa_clearb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN); 72b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN); 73b285192aSMauro Carvalho Chehab 74b285192aSMauro Carvalho Chehab gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2); 75b285192aSMauro Carvalho Chehab if (ir->polling) { 76b285192aSMauro Carvalho Chehab if (ir->last_gpio == gpio) 77b285192aSMauro Carvalho Chehab return 0; 78b285192aSMauro Carvalho Chehab ir->last_gpio = gpio; 79b285192aSMauro Carvalho Chehab } 80b285192aSMauro Carvalho Chehab 81b285192aSMauro Carvalho Chehab data = ir_extract_bits(gpio, ir->mask_keycode); 826be5b1a1SMauro Carvalho Chehab input_dbg("build_key gpio=0x%x mask=0x%x data=%d\n", 83b285192aSMauro Carvalho Chehab gpio, ir->mask_keycode, data); 84b285192aSMauro Carvalho Chehab 85b285192aSMauro Carvalho Chehab switch (dev->board) { 86b285192aSMauro Carvalho Chehab case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG: 87b285192aSMauro Carvalho Chehab if (data == ir->mask_keycode) 88b285192aSMauro Carvalho Chehab rc_keyup(ir->dev); 89b285192aSMauro Carvalho Chehab else 90120703f9SDavid Härdeman rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0); 91b285192aSMauro Carvalho Chehab return 0; 92b285192aSMauro Carvalho Chehab } 93b285192aSMauro Carvalho Chehab 94b285192aSMauro Carvalho Chehab if (ir->polling) { 95b285192aSMauro Carvalho Chehab if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) || 96b285192aSMauro Carvalho Chehab (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { 97120703f9SDavid Härdeman rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0); 98b285192aSMauro Carvalho Chehab } else { 99b285192aSMauro Carvalho Chehab rc_keyup(ir->dev); 100b285192aSMauro Carvalho Chehab } 101b285192aSMauro Carvalho Chehab } 102b285192aSMauro Carvalho Chehab else { /* IRQ driven mode - handle key press and release in one go */ 103b285192aSMauro Carvalho Chehab if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) || 104b285192aSMauro Carvalho Chehab (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { 105120703f9SDavid Härdeman rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0); 106b285192aSMauro Carvalho Chehab rc_keyup(ir->dev); 107b285192aSMauro Carvalho Chehab } 108b285192aSMauro Carvalho Chehab } 109b285192aSMauro Carvalho Chehab 110b285192aSMauro Carvalho Chehab return 0; 111b285192aSMauro Carvalho Chehab } 112b285192aSMauro Carvalho Chehab 113b285192aSMauro Carvalho Chehab /* --------------------- Chip specific I2C key builders ----------------- */ 114b285192aSMauro Carvalho Chehab 1154dd9bb91SDavid Härdeman static int get_key_flydvb_trio(struct IR_i2c *ir, enum rc_type *protocol, 1164dd9bb91SDavid Härdeman u32 *scancode, u8 *toggle) 117b285192aSMauro Carvalho Chehab { 118b285192aSMauro Carvalho Chehab int gpio; 119b285192aSMauro Carvalho Chehab int attempt = 0; 120b285192aSMauro Carvalho Chehab unsigned char b; 121b285192aSMauro Carvalho Chehab 122b285192aSMauro Carvalho Chehab /* We need this to access GPI Used by the saa_readl macro. */ 123b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = ir->c->adapter->algo_data; 124b285192aSMauro Carvalho Chehab 125b285192aSMauro Carvalho Chehab if (dev == NULL) { 1266be5b1a1SMauro Carvalho Chehab ir_dbg(ir, "get_key_flydvb_trio: " 127b285192aSMauro Carvalho Chehab "ir->c->adapter->algo_data is NULL!\n"); 128b285192aSMauro Carvalho Chehab return -EIO; 129b285192aSMauro Carvalho Chehab } 130b285192aSMauro Carvalho Chehab 131b285192aSMauro Carvalho Chehab /* rising SAA7134_GPIGPRESCAN reads the status */ 132b285192aSMauro Carvalho Chehab saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 133b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 134b285192aSMauro Carvalho Chehab 135b285192aSMauro Carvalho Chehab gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2); 136b285192aSMauro Carvalho Chehab 137b285192aSMauro Carvalho Chehab if (0x40000 & ~gpio) 138b285192aSMauro Carvalho Chehab return 0; /* No button press */ 139b285192aSMauro Carvalho Chehab 140b285192aSMauro Carvalho Chehab /* poll IR chip */ 141b285192aSMauro Carvalho Chehab /* weak up the IR chip */ 142b285192aSMauro Carvalho Chehab b = 0; 143b285192aSMauro Carvalho Chehab 144b285192aSMauro Carvalho Chehab while (1 != i2c_master_send(ir->c, &b, 1)) { 145b285192aSMauro Carvalho Chehab if ((attempt++) < 10) { 146b285192aSMauro Carvalho Chehab /* 147b285192aSMauro Carvalho Chehab * wait a bit for next attempt - 148b285192aSMauro Carvalho Chehab * I don't know how make it better 149b285192aSMauro Carvalho Chehab */ 150b285192aSMauro Carvalho Chehab msleep(10); 151b285192aSMauro Carvalho Chehab continue; 152b285192aSMauro Carvalho Chehab } 1536be5b1a1SMauro Carvalho Chehab ir_dbg(ir, "send wake up byte to pic16C505 (IR chip)" 154b285192aSMauro Carvalho Chehab "failed %dx\n", attempt); 155b285192aSMauro Carvalho Chehab return -EIO; 156b285192aSMauro Carvalho Chehab } 157b285192aSMauro Carvalho Chehab if (1 != i2c_master_recv(ir->c, &b, 1)) { 1586be5b1a1SMauro Carvalho Chehab ir_dbg(ir, "read error\n"); 159b285192aSMauro Carvalho Chehab return -EIO; 160b285192aSMauro Carvalho Chehab } 161b285192aSMauro Carvalho Chehab 1624dd9bb91SDavid Härdeman *protocol = RC_TYPE_UNKNOWN; 1634dd9bb91SDavid Härdeman *scancode = b; 1644dd9bb91SDavid Härdeman *toggle = 0; 165b285192aSMauro Carvalho Chehab return 1; 166b285192aSMauro Carvalho Chehab } 167b285192aSMauro Carvalho Chehab 1684dd9bb91SDavid Härdeman static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, enum rc_type *protocol, 1694dd9bb91SDavid Härdeman u32 *scancode, u8 *toggle) 170b285192aSMauro Carvalho Chehab { 171b285192aSMauro Carvalho Chehab unsigned char b; 172b285192aSMauro Carvalho Chehab int gpio; 173b285192aSMauro Carvalho Chehab 174b285192aSMauro Carvalho Chehab /* <dev> is needed to access GPIO. Used by the saa_readl macro. */ 175b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = ir->c->adapter->algo_data; 176b285192aSMauro Carvalho Chehab if (dev == NULL) { 1776be5b1a1SMauro Carvalho Chehab ir_dbg(ir, "get_key_msi_tvanywhere_plus: " 178b285192aSMauro Carvalho Chehab "ir->c->adapter->algo_data is NULL!\n"); 179b285192aSMauro Carvalho Chehab return -EIO; 180b285192aSMauro Carvalho Chehab } 181b285192aSMauro Carvalho Chehab 182b285192aSMauro Carvalho Chehab /* rising SAA7134_GPIO_GPRESCAN reads the status */ 183b285192aSMauro Carvalho Chehab 184b285192aSMauro Carvalho Chehab saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 185b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 186b285192aSMauro Carvalho Chehab 187b285192aSMauro Carvalho Chehab gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2); 188b285192aSMauro Carvalho Chehab 189b285192aSMauro Carvalho Chehab /* GPIO&0x40 is pulsed low when a button is pressed. Don't do 190b285192aSMauro Carvalho Chehab I2C receive if gpio&0x40 is not low. */ 191b285192aSMauro Carvalho Chehab 192b285192aSMauro Carvalho Chehab if (gpio & 0x40) 193b285192aSMauro Carvalho Chehab return 0; /* No button press */ 194b285192aSMauro Carvalho Chehab 195b285192aSMauro Carvalho Chehab /* GPIO says there is a button press. Get it. */ 196b285192aSMauro Carvalho Chehab 197b285192aSMauro Carvalho Chehab if (1 != i2c_master_recv(ir->c, &b, 1)) { 1986be5b1a1SMauro Carvalho Chehab ir_dbg(ir, "read error\n"); 199b285192aSMauro Carvalho Chehab return -EIO; 200b285192aSMauro Carvalho Chehab } 201b285192aSMauro Carvalho Chehab 202b285192aSMauro Carvalho Chehab /* No button press */ 203b285192aSMauro Carvalho Chehab 204b285192aSMauro Carvalho Chehab if (b == 0xff) 205b285192aSMauro Carvalho Chehab return 0; 206b285192aSMauro Carvalho Chehab 207b285192aSMauro Carvalho Chehab /* Button pressed */ 208b285192aSMauro Carvalho Chehab 2096be5b1a1SMauro Carvalho Chehab input_dbg("get_key_msi_tvanywhere_plus: Key = 0x%02X\n", b); 2104dd9bb91SDavid Härdeman *protocol = RC_TYPE_UNKNOWN; 2114dd9bb91SDavid Härdeman *scancode = b; 2124dd9bb91SDavid Härdeman *toggle = 0; 213b285192aSMauro Carvalho Chehab return 1; 214b285192aSMauro Carvalho Chehab } 215b285192aSMauro Carvalho Chehab 216b285192aSMauro Carvalho Chehab /* copied and modified from get_key_msi_tvanywhere_plus() */ 2174dd9bb91SDavid Härdeman static int get_key_kworld_pc150u(struct IR_i2c *ir, enum rc_type *protocol, 2184dd9bb91SDavid Härdeman u32 *scancode, u8 *toggle) 219b285192aSMauro Carvalho Chehab { 220b285192aSMauro Carvalho Chehab unsigned char b; 221b285192aSMauro Carvalho Chehab unsigned int gpio; 222b285192aSMauro Carvalho Chehab 223b285192aSMauro Carvalho Chehab /* <dev> is needed to access GPIO. Used by the saa_readl macro. */ 224b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = ir->c->adapter->algo_data; 225b285192aSMauro Carvalho Chehab if (dev == NULL) { 2266be5b1a1SMauro Carvalho Chehab ir_dbg(ir, "get_key_kworld_pc150u: " 227b285192aSMauro Carvalho Chehab "ir->c->adapter->algo_data is NULL!\n"); 228b285192aSMauro Carvalho Chehab return -EIO; 229b285192aSMauro Carvalho Chehab } 230b285192aSMauro Carvalho Chehab 231b285192aSMauro Carvalho Chehab /* rising SAA7134_GPIO_GPRESCAN reads the status */ 232b285192aSMauro Carvalho Chehab 233b285192aSMauro Carvalho Chehab saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 234b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 235b285192aSMauro Carvalho Chehab 236b285192aSMauro Carvalho Chehab gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2); 237b285192aSMauro Carvalho Chehab 238b285192aSMauro Carvalho Chehab /* GPIO&0x100 is pulsed low when a button is pressed. Don't do 239b285192aSMauro Carvalho Chehab I2C receive if gpio&0x100 is not low. */ 240b285192aSMauro Carvalho Chehab 241b285192aSMauro Carvalho Chehab if (gpio & 0x100) 242b285192aSMauro Carvalho Chehab return 0; /* No button press */ 243b285192aSMauro Carvalho Chehab 244b285192aSMauro Carvalho Chehab /* GPIO says there is a button press. Get it. */ 245b285192aSMauro Carvalho Chehab 246b285192aSMauro Carvalho Chehab if (1 != i2c_master_recv(ir->c, &b, 1)) { 2476be5b1a1SMauro Carvalho Chehab ir_dbg(ir, "read error\n"); 248b285192aSMauro Carvalho Chehab return -EIO; 249b285192aSMauro Carvalho Chehab } 250b285192aSMauro Carvalho Chehab 251b285192aSMauro Carvalho Chehab /* No button press */ 252b285192aSMauro Carvalho Chehab 253b285192aSMauro Carvalho Chehab if (b == 0xff) 254b285192aSMauro Carvalho Chehab return 0; 255b285192aSMauro Carvalho Chehab 256b285192aSMauro Carvalho Chehab /* Button pressed */ 257b285192aSMauro Carvalho Chehab 2586be5b1a1SMauro Carvalho Chehab input_dbg("get_key_kworld_pc150u: Key = 0x%02X\n", b); 2594dd9bb91SDavid Härdeman *protocol = RC_TYPE_UNKNOWN; 2604dd9bb91SDavid Härdeman *scancode = b; 2614dd9bb91SDavid Härdeman *toggle = 0; 262b285192aSMauro Carvalho Chehab return 1; 263b285192aSMauro Carvalho Chehab } 264b285192aSMauro Carvalho Chehab 2654dd9bb91SDavid Härdeman static int get_key_purpletv(struct IR_i2c *ir, enum rc_type *protocol, 2664dd9bb91SDavid Härdeman u32 *scancode, u8 *toggle) 267b285192aSMauro Carvalho Chehab { 268b285192aSMauro Carvalho Chehab unsigned char b; 269b285192aSMauro Carvalho Chehab 270b285192aSMauro Carvalho Chehab /* poll IR chip */ 271b285192aSMauro Carvalho Chehab if (1 != i2c_master_recv(ir->c, &b, 1)) { 2726be5b1a1SMauro Carvalho Chehab ir_dbg(ir, "read error\n"); 273b285192aSMauro Carvalho Chehab return -EIO; 274b285192aSMauro Carvalho Chehab } 275b285192aSMauro Carvalho Chehab 276b285192aSMauro Carvalho Chehab /* no button press */ 277b285192aSMauro Carvalho Chehab if (b==0) 278b285192aSMauro Carvalho Chehab return 0; 279b285192aSMauro Carvalho Chehab 280b285192aSMauro Carvalho Chehab /* repeating */ 281b285192aSMauro Carvalho Chehab if (b & 0x80) 282b285192aSMauro Carvalho Chehab return 1; 283b285192aSMauro Carvalho Chehab 2844dd9bb91SDavid Härdeman *protocol = RC_TYPE_UNKNOWN; 2854dd9bb91SDavid Härdeman *scancode = b; 2864dd9bb91SDavid Härdeman *toggle = 0; 287b285192aSMauro Carvalho Chehab return 1; 288b285192aSMauro Carvalho Chehab } 289b285192aSMauro Carvalho Chehab 2904dd9bb91SDavid Härdeman static int get_key_hvr1110(struct IR_i2c *ir, enum rc_type *protocol, 2914dd9bb91SDavid Härdeman u32 *scancode, u8 *toggle) 292b285192aSMauro Carvalho Chehab { 293b285192aSMauro Carvalho Chehab unsigned char buf[5]; 294b285192aSMauro Carvalho Chehab 295b285192aSMauro Carvalho Chehab /* poll IR chip */ 296b285192aSMauro Carvalho Chehab if (5 != i2c_master_recv(ir->c, buf, 5)) 297b285192aSMauro Carvalho Chehab return -EIO; 298b285192aSMauro Carvalho Chehab 299b285192aSMauro Carvalho Chehab /* Check if some key were pressed */ 300b285192aSMauro Carvalho Chehab if (!(buf[0] & 0x80)) 301b285192aSMauro Carvalho Chehab return 0; 302b285192aSMauro Carvalho Chehab 303b285192aSMauro Carvalho Chehab /* 304b285192aSMauro Carvalho Chehab * buf[3] & 0x80 is always high. 305b285192aSMauro Carvalho Chehab * buf[3] & 0x40 is a parity bit. A repeat event is marked 306b285192aSMauro Carvalho Chehab * by preserving it into two separate readings 307b285192aSMauro Carvalho Chehab * buf[4] bits 0 and 1, and buf[1] and buf[2] are always 308b285192aSMauro Carvalho Chehab * zero. 3094dd9bb91SDavid Härdeman * 3104dd9bb91SDavid Härdeman * Note that the keymap which the hvr1110 uses is RC5. 3114dd9bb91SDavid Härdeman * 3124dd9bb91SDavid Härdeman * FIXME: start bits could maybe be used...? 313b285192aSMauro Carvalho Chehab */ 3144dd9bb91SDavid Härdeman *protocol = RC_TYPE_RC5; 3154dd9bb91SDavid Härdeman *scancode = RC_SCANCODE_RC5(buf[3] & 0x1f, buf[4] >> 2); 3164dd9bb91SDavid Härdeman *toggle = !!(buf[3] & 0x40); 317b285192aSMauro Carvalho Chehab return 1; 318b285192aSMauro Carvalho Chehab } 319b285192aSMauro Carvalho Chehab 320b285192aSMauro Carvalho Chehab 3214dd9bb91SDavid Härdeman static int get_key_beholdm6xx(struct IR_i2c *ir, enum rc_type *protocol, 3224dd9bb91SDavid Härdeman u32 *scancode, u8 *toggle) 323b285192aSMauro Carvalho Chehab { 324b285192aSMauro Carvalho Chehab unsigned char data[12]; 325b285192aSMauro Carvalho Chehab u32 gpio; 326b285192aSMauro Carvalho Chehab 327b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = ir->c->adapter->algo_data; 328b285192aSMauro Carvalho Chehab 329b285192aSMauro Carvalho Chehab /* rising SAA7134_GPIO_GPRESCAN reads the status */ 330b285192aSMauro Carvalho Chehab saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 331b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 332b285192aSMauro Carvalho Chehab 333b285192aSMauro Carvalho Chehab gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2); 334b285192aSMauro Carvalho Chehab 335b285192aSMauro Carvalho Chehab if (0x400000 & ~gpio) 336b285192aSMauro Carvalho Chehab return 0; /* No button press */ 337b285192aSMauro Carvalho Chehab 338b285192aSMauro Carvalho Chehab ir->c->addr = 0x5a >> 1; 339b285192aSMauro Carvalho Chehab 340b285192aSMauro Carvalho Chehab if (12 != i2c_master_recv(ir->c, data, 12)) { 3416be5b1a1SMauro Carvalho Chehab ir_dbg(ir, "read error\n"); 342b285192aSMauro Carvalho Chehab return -EIO; 343b285192aSMauro Carvalho Chehab } 344b285192aSMauro Carvalho Chehab 345b285192aSMauro Carvalho Chehab if (data[9] != (unsigned char)(~data[8])) 346b285192aSMauro Carvalho Chehab return 0; 347b285192aSMauro Carvalho Chehab 3484dd9bb91SDavid Härdeman *protocol = RC_TYPE_NEC; 3490bc56cbeSDavid Härdeman *scancode = RC_SCANCODE_NECX(data[11] << 8 | data[10], data[9]); 3504dd9bb91SDavid Härdeman *toggle = 0; 351b285192aSMauro Carvalho Chehab return 1; 352b285192aSMauro Carvalho Chehab } 353b285192aSMauro Carvalho Chehab 354b285192aSMauro Carvalho Chehab /* Common (grey or coloured) pinnacle PCTV remote handling 355b285192aSMauro Carvalho Chehab * 356b285192aSMauro Carvalho Chehab */ 3574dd9bb91SDavid Härdeman static int get_key_pinnacle(struct IR_i2c *ir, enum rc_type *protocol, 3584dd9bb91SDavid Härdeman u32 *scancode, u8 *toggle, int parity_offset, 3594dd9bb91SDavid Härdeman int marker, int code_modulo) 360b285192aSMauro Carvalho Chehab { 361b285192aSMauro Carvalho Chehab unsigned char b[4]; 362b285192aSMauro Carvalho Chehab unsigned int start = 0,parity = 0,code = 0; 363b285192aSMauro Carvalho Chehab 364b285192aSMauro Carvalho Chehab /* poll IR chip */ 365b285192aSMauro Carvalho Chehab if (4 != i2c_master_recv(ir->c, b, 4)) { 3666be5b1a1SMauro Carvalho Chehab ir_dbg(ir, "read error\n"); 367b285192aSMauro Carvalho Chehab return -EIO; 368b285192aSMauro Carvalho Chehab } 369b285192aSMauro Carvalho Chehab 370b285192aSMauro Carvalho Chehab for (start = 0; start < ARRAY_SIZE(b); start++) { 371b285192aSMauro Carvalho Chehab if (b[start] == marker) { 372b285192aSMauro Carvalho Chehab code=b[(start+parity_offset + 1) % 4]; 373b285192aSMauro Carvalho Chehab parity=b[(start+parity_offset) % 4]; 374b285192aSMauro Carvalho Chehab } 375b285192aSMauro Carvalho Chehab } 376b285192aSMauro Carvalho Chehab 377b285192aSMauro Carvalho Chehab /* Empty Request */ 378b285192aSMauro Carvalho Chehab if (parity == 0) 379b285192aSMauro Carvalho Chehab return 0; 380b285192aSMauro Carvalho Chehab 381b285192aSMauro Carvalho Chehab /* Repeating... */ 382b285192aSMauro Carvalho Chehab if (ir->old == parity) 383b285192aSMauro Carvalho Chehab return 0; 384b285192aSMauro Carvalho Chehab 385b285192aSMauro Carvalho Chehab ir->old = parity; 386b285192aSMauro Carvalho Chehab 387b285192aSMauro Carvalho Chehab /* drop special codes when a key is held down a long time for the grey controller 388b285192aSMauro Carvalho Chehab In this case, the second bit of the code is asserted */ 389b285192aSMauro Carvalho Chehab if (marker == 0xfe && (code & 0x40)) 390b285192aSMauro Carvalho Chehab return 0; 391b285192aSMauro Carvalho Chehab 392b285192aSMauro Carvalho Chehab code %= code_modulo; 393b285192aSMauro Carvalho Chehab 3944dd9bb91SDavid Härdeman *protocol = RC_TYPE_UNKNOWN; 3954dd9bb91SDavid Härdeman *scancode = code; 3964dd9bb91SDavid Härdeman *toggle = 0; 397b285192aSMauro Carvalho Chehab 3986be5b1a1SMauro Carvalho Chehab ir_dbg(ir, "Pinnacle PCTV key %02x\n", code); 399b285192aSMauro Carvalho Chehab return 1; 400b285192aSMauro Carvalho Chehab } 401b285192aSMauro Carvalho Chehab 402b285192aSMauro Carvalho Chehab /* The grey pinnacle PCTV remote 403b285192aSMauro Carvalho Chehab * 404b285192aSMauro Carvalho Chehab * There are one issue with this remote: 405b285192aSMauro Carvalho Chehab * - I2c packet does not change when the same key is pressed quickly. The workaround 406b285192aSMauro Carvalho Chehab * is to hold down each key for about half a second, so that another code is generated 407b285192aSMauro Carvalho Chehab * in the i2c packet, and the function can distinguish key presses. 408b285192aSMauro Carvalho Chehab * 409b285192aSMauro Carvalho Chehab * Sylvain Pasche <sylvain.pasche@gmail.com> 410b285192aSMauro Carvalho Chehab */ 4114dd9bb91SDavid Härdeman static int get_key_pinnacle_grey(struct IR_i2c *ir, enum rc_type *protocol, 4124dd9bb91SDavid Härdeman u32 *scancode, u8 *toggle) 413b285192aSMauro Carvalho Chehab { 414b285192aSMauro Carvalho Chehab 4154dd9bb91SDavid Härdeman return get_key_pinnacle(ir, protocol, scancode, toggle, 1, 0xfe, 0xff); 416b285192aSMauro Carvalho Chehab } 417b285192aSMauro Carvalho Chehab 418b285192aSMauro Carvalho Chehab 419b285192aSMauro Carvalho Chehab /* The new pinnacle PCTV remote (with the colored buttons) 420b285192aSMauro Carvalho Chehab * 421b285192aSMauro Carvalho Chehab * Ricardo Cerqueira <v4l@cerqueira.org> 422b285192aSMauro Carvalho Chehab */ 4234dd9bb91SDavid Härdeman static int get_key_pinnacle_color(struct IR_i2c *ir, enum rc_type *protocol, 4244dd9bb91SDavid Härdeman u32 *scancode, u8 *toggle) 425b285192aSMauro Carvalho Chehab { 426b285192aSMauro Carvalho Chehab /* code_modulo parameter (0x88) is used to reduce code value to fit inside IR_KEYTAB_SIZE 427b285192aSMauro Carvalho Chehab * 428b285192aSMauro Carvalho Chehab * this is the only value that results in 42 unique 429b285192aSMauro Carvalho Chehab * codes < 128 430b285192aSMauro Carvalho Chehab */ 431b285192aSMauro Carvalho Chehab 4324dd9bb91SDavid Härdeman return get_key_pinnacle(ir, protocol, scancode, toggle, 2, 0x80, 0x88); 433b285192aSMauro Carvalho Chehab } 434b285192aSMauro Carvalho Chehab 435b285192aSMauro Carvalho Chehab void saa7134_input_irq(struct saa7134_dev *dev) 436b285192aSMauro Carvalho Chehab { 437b285192aSMauro Carvalho Chehab struct saa7134_card_ir *ir; 438b285192aSMauro Carvalho Chehab 439b285192aSMauro Carvalho Chehab if (!dev || !dev->remote) 440b285192aSMauro Carvalho Chehab return; 441b285192aSMauro Carvalho Chehab 442b285192aSMauro Carvalho Chehab ir = dev->remote; 443b285192aSMauro Carvalho Chehab if (!ir->running) 444b285192aSMauro Carvalho Chehab return; 445b285192aSMauro Carvalho Chehab 446b285192aSMauro Carvalho Chehab if (!ir->polling && !ir->raw_decode) { 447b285192aSMauro Carvalho Chehab build_key(dev); 448b285192aSMauro Carvalho Chehab } else if (ir->raw_decode) { 449b285192aSMauro Carvalho Chehab saa7134_raw_decode_irq(dev); 450b285192aSMauro Carvalho Chehab } 451b285192aSMauro Carvalho Chehab } 452b285192aSMauro Carvalho Chehab 453b285192aSMauro Carvalho Chehab static void saa7134_input_timer(unsigned long data) 454b285192aSMauro Carvalho Chehab { 455b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = (struct saa7134_dev *)data; 456b285192aSMauro Carvalho Chehab struct saa7134_card_ir *ir = dev->remote; 457b285192aSMauro Carvalho Chehab 458b285192aSMauro Carvalho Chehab build_key(dev); 459b285192aSMauro Carvalho Chehab mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); 460b285192aSMauro Carvalho Chehab } 461b285192aSMauro Carvalho Chehab 462b285192aSMauro Carvalho Chehab static void ir_raw_decode_timer_end(unsigned long data) 463b285192aSMauro Carvalho Chehab { 464b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = (struct saa7134_dev *)data; 465b285192aSMauro Carvalho Chehab 466b285192aSMauro Carvalho Chehab ir_raw_event_handle(dev->remote->dev); 467b285192aSMauro Carvalho Chehab } 468b285192aSMauro Carvalho Chehab 469b285192aSMauro Carvalho Chehab static int __saa7134_ir_start(void *priv) 470b285192aSMauro Carvalho Chehab { 471b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = priv; 472b285192aSMauro Carvalho Chehab struct saa7134_card_ir *ir; 473b285192aSMauro Carvalho Chehab 474b285192aSMauro Carvalho Chehab if (!dev || !dev->remote) 475b285192aSMauro Carvalho Chehab return -EINVAL; 476b285192aSMauro Carvalho Chehab 477b285192aSMauro Carvalho Chehab ir = dev->remote; 478b285192aSMauro Carvalho Chehab if (ir->running) 479b285192aSMauro Carvalho Chehab return 0; 480b285192aSMauro Carvalho Chehab 481b285192aSMauro Carvalho Chehab /* Moved here from saa7134_input_init1() because the latter 482b285192aSMauro Carvalho Chehab * is not called on device resume */ 483b285192aSMauro Carvalho Chehab switch (dev->board) { 484b285192aSMauro Carvalho Chehab case SAA7134_BOARD_MD2819: 485b285192aSMauro Carvalho Chehab case SAA7134_BOARD_KWORLD_VSTREAM_XPERT: 486b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_305: 487b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_307: 488de983454SDmitry Eremin-Solenikov case SAA7134_BOARD_AVERMEDIA_505: 489b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_305: 490b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_505: 491b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_307: 492b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_507: 493b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_507UA: 494b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_GO_007_FM: 495b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_M102: 496b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS: 497b285192aSMauro Carvalho Chehab /* Without this we won't receive key up events */ 498b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE0, 0x4); 499b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); 500b285192aSMauro Carvalho Chehab break; 501b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_777: 502b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_A16AR: 503b285192aSMauro Carvalho Chehab /* Without this we won't receive key up events */ 504b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE1, 0x1); 505b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1); 506b285192aSMauro Carvalho Chehab break; 507b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_A16D: 508b285192aSMauro Carvalho Chehab /* Without this we won't receive key up events */ 509b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE1, 0x1); 510b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1); 511b285192aSMauro Carvalho Chehab break; 512b285192aSMauro Carvalho Chehab case SAA7134_BOARD_GOTVIEW_7135: 513b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE1, 0x80); 514b285192aSMauro Carvalho Chehab break; 515b285192aSMauro Carvalho Chehab } 516b285192aSMauro Carvalho Chehab 517b285192aSMauro Carvalho Chehab ir->running = true; 518b285192aSMauro Carvalho Chehab 519b285192aSMauro Carvalho Chehab if (ir->polling) { 520b285192aSMauro Carvalho Chehab setup_timer(&ir->timer, saa7134_input_timer, 521b285192aSMauro Carvalho Chehab (unsigned long)dev); 522b285192aSMauro Carvalho Chehab ir->timer.expires = jiffies + HZ; 523b285192aSMauro Carvalho Chehab add_timer(&ir->timer); 524b285192aSMauro Carvalho Chehab } else if (ir->raw_decode) { 525b285192aSMauro Carvalho Chehab /* set timer_end for code completion */ 526b285192aSMauro Carvalho Chehab setup_timer(&ir->timer, ir_raw_decode_timer_end, 527b285192aSMauro Carvalho Chehab (unsigned long)dev); 528b285192aSMauro Carvalho Chehab } 529b285192aSMauro Carvalho Chehab 530b285192aSMauro Carvalho Chehab return 0; 531b285192aSMauro Carvalho Chehab } 532b285192aSMauro Carvalho Chehab 533b285192aSMauro Carvalho Chehab static void __saa7134_ir_stop(void *priv) 534b285192aSMauro Carvalho Chehab { 535b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = priv; 536b285192aSMauro Carvalho Chehab struct saa7134_card_ir *ir; 537b285192aSMauro Carvalho Chehab 538b285192aSMauro Carvalho Chehab if (!dev || !dev->remote) 539b285192aSMauro Carvalho Chehab return; 540b285192aSMauro Carvalho Chehab 541b285192aSMauro Carvalho Chehab ir = dev->remote; 542b285192aSMauro Carvalho Chehab if (!ir->running) 543b285192aSMauro Carvalho Chehab return; 544b285192aSMauro Carvalho Chehab 545b285192aSMauro Carvalho Chehab if (ir->polling || ir->raw_decode) 546b285192aSMauro Carvalho Chehab del_timer_sync(&ir->timer); 547b285192aSMauro Carvalho Chehab 548b285192aSMauro Carvalho Chehab ir->running = false; 549b285192aSMauro Carvalho Chehab 550b285192aSMauro Carvalho Chehab return; 551b285192aSMauro Carvalho Chehab } 552b285192aSMauro Carvalho Chehab 553b285192aSMauro Carvalho Chehab int saa7134_ir_start(struct saa7134_dev *dev) 554b285192aSMauro Carvalho Chehab { 555b285192aSMauro Carvalho Chehab if (dev->remote->users) 556b285192aSMauro Carvalho Chehab return __saa7134_ir_start(dev); 557b285192aSMauro Carvalho Chehab 558b285192aSMauro Carvalho Chehab return 0; 559b285192aSMauro Carvalho Chehab } 560b285192aSMauro Carvalho Chehab 561b285192aSMauro Carvalho Chehab void saa7134_ir_stop(struct saa7134_dev *dev) 562b285192aSMauro Carvalho Chehab { 563b285192aSMauro Carvalho Chehab if (dev->remote->users) 564b285192aSMauro Carvalho Chehab __saa7134_ir_stop(dev); 565b285192aSMauro Carvalho Chehab } 566b285192aSMauro Carvalho Chehab 567b285192aSMauro Carvalho Chehab static int saa7134_ir_open(struct rc_dev *rc) 568b285192aSMauro Carvalho Chehab { 569b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = rc->priv; 570b285192aSMauro Carvalho Chehab 571b285192aSMauro Carvalho Chehab dev->remote->users++; 572b285192aSMauro Carvalho Chehab return __saa7134_ir_start(dev); 573b285192aSMauro Carvalho Chehab } 574b285192aSMauro Carvalho Chehab 575b285192aSMauro Carvalho Chehab static void saa7134_ir_close(struct rc_dev *rc) 576b285192aSMauro Carvalho Chehab { 577b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = rc->priv; 578b285192aSMauro Carvalho Chehab 579b285192aSMauro Carvalho Chehab dev->remote->users--; 580b285192aSMauro Carvalho Chehab if (!dev->remote->users) 581b285192aSMauro Carvalho Chehab __saa7134_ir_stop(dev); 582b285192aSMauro Carvalho Chehab } 583b285192aSMauro Carvalho Chehab 584b285192aSMauro Carvalho Chehab int saa7134_input_init1(struct saa7134_dev *dev) 585b285192aSMauro Carvalho Chehab { 586b285192aSMauro Carvalho Chehab struct saa7134_card_ir *ir; 587b285192aSMauro Carvalho Chehab struct rc_dev *rc; 588b285192aSMauro Carvalho Chehab char *ir_codes = NULL; 589b285192aSMauro Carvalho Chehab u32 mask_keycode = 0; 590b285192aSMauro Carvalho Chehab u32 mask_keydown = 0; 591b285192aSMauro Carvalho Chehab u32 mask_keyup = 0; 592b285192aSMauro Carvalho Chehab unsigned polling = 0; 593b285192aSMauro Carvalho Chehab bool raw_decode = false; 594b285192aSMauro Carvalho Chehab int err; 595b285192aSMauro Carvalho Chehab 596b285192aSMauro Carvalho Chehab if (dev->has_remote != SAA7134_REMOTE_GPIO) 597b285192aSMauro Carvalho Chehab return -ENODEV; 598b285192aSMauro Carvalho Chehab if (disable_ir) 599b285192aSMauro Carvalho Chehab return -ENODEV; 600b285192aSMauro Carvalho Chehab 601b285192aSMauro Carvalho Chehab /* detect & configure */ 602b285192aSMauro Carvalho Chehab switch (dev->board) { 603b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYVIDEO2000: 604b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYVIDEO3000: 605b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYTVPLATINUM_FM: 606b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYTVPLATINUM_MINI2: 607b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM: 608b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_FLYVIDEO; 609b285192aSMauro Carvalho Chehab mask_keycode = 0xEC00000; 610b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; 611b285192aSMauro Carvalho Chehab break; 612b285192aSMauro Carvalho Chehab case SAA7134_BOARD_CINERGY400: 613b285192aSMauro Carvalho Chehab case SAA7134_BOARD_CINERGY600: 614b285192aSMauro Carvalho Chehab case SAA7134_BOARD_CINERGY600_MK3: 615b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_CINERGY; 616b285192aSMauro Carvalho Chehab mask_keycode = 0x00003f; 617b285192aSMauro Carvalho Chehab mask_keyup = 0x040000; 618b285192aSMauro Carvalho Chehab break; 619b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ECS_TVP3XP: 620b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ECS_TVP3XP_4CB5: 621b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_EZTV; 622b285192aSMauro Carvalho Chehab mask_keycode = 0x00017c; 623b285192aSMauro Carvalho Chehab mask_keyup = 0x000002; 624b285192aSMauro Carvalho Chehab polling = 50; // ms 625b285192aSMauro Carvalho Chehab break; 626b285192aSMauro Carvalho Chehab case SAA7134_BOARD_KWORLD_XPERT: 627b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVACSSMARTTV: 628b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_PIXELVIEW; 629b285192aSMauro Carvalho Chehab mask_keycode = 0x00001F; 630b285192aSMauro Carvalho Chehab mask_keyup = 0x000020; 631b285192aSMauro Carvalho Chehab polling = 50; // ms 632b285192aSMauro Carvalho Chehab break; 633b285192aSMauro Carvalho Chehab case SAA7134_BOARD_MD2819: 634b285192aSMauro Carvalho Chehab case SAA7134_BOARD_KWORLD_VSTREAM_XPERT: 635b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_305: 636b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_307: 637de983454SDmitry Eremin-Solenikov case SAA7134_BOARD_AVERMEDIA_505: 638b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_305: 639b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_505: 640b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_307: 641b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_507: 642b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_507UA: 643b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_GO_007_FM: 644b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_M102: 645b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS: 646b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_AVERMEDIA; 647b285192aSMauro Carvalho Chehab mask_keycode = 0x0007C8; 648b285192aSMauro Carvalho Chehab mask_keydown = 0x000010; 649b285192aSMauro Carvalho Chehab polling = 50; // ms 650b285192aSMauro Carvalho Chehab /* GPIO stuff moved to __saa7134_ir_start() */ 651b285192aSMauro Carvalho Chehab break; 652b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_M135A: 653b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_AVERMEDIA_M135A; 654b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ 655b285192aSMauro Carvalho Chehab mask_keyup = 0x0040000; 656b285192aSMauro Carvalho Chehab mask_keycode = 0xffff; 657b285192aSMauro Carvalho Chehab raw_decode = true; 658b285192aSMauro Carvalho Chehab break; 659b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_M733A: 660b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_AVERMEDIA_M733A_RM_K6; 661b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; 662b285192aSMauro Carvalho Chehab mask_keyup = 0x0040000; 663b285192aSMauro Carvalho Chehab mask_keycode = 0xffff; 664b285192aSMauro Carvalho Chehab raw_decode = true; 665b285192aSMauro Carvalho Chehab break; 666b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_777: 667b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_A16AR: 668b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_AVERMEDIA; 669b285192aSMauro Carvalho Chehab mask_keycode = 0x02F200; 670b285192aSMauro Carvalho Chehab mask_keydown = 0x000400; 671b285192aSMauro Carvalho Chehab polling = 50; // ms 672b285192aSMauro Carvalho Chehab /* GPIO stuff moved to __saa7134_ir_start() */ 673b285192aSMauro Carvalho Chehab break; 674b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_A16D: 675b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_AVERMEDIA_A16D; 676b285192aSMauro Carvalho Chehab mask_keycode = 0x02F200; 677b285192aSMauro Carvalho Chehab mask_keydown = 0x000400; 678b285192aSMauro Carvalho Chehab polling = 50; /* ms */ 679b285192aSMauro Carvalho Chehab /* GPIO stuff moved to __saa7134_ir_start() */ 680b285192aSMauro Carvalho Chehab break; 681b285192aSMauro Carvalho Chehab case SAA7134_BOARD_KWORLD_TERMINATOR: 682b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_PIXELVIEW; 683b285192aSMauro Carvalho Chehab mask_keycode = 0x00001f; 684b285192aSMauro Carvalho Chehab mask_keyup = 0x000060; 685b285192aSMauro Carvalho Chehab polling = 50; // ms 686b285192aSMauro Carvalho Chehab break; 687b285192aSMauro Carvalho Chehab case SAA7134_BOARD_MANLI_MTV001: 688b285192aSMauro Carvalho Chehab case SAA7134_BOARD_MANLI_MTV002: 689b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_MANLI; 690b285192aSMauro Carvalho Chehab mask_keycode = 0x001f00; 691b285192aSMauro Carvalho Chehab mask_keyup = 0x004000; 692b285192aSMauro Carvalho Chehab polling = 50; /* ms */ 693b285192aSMauro Carvalho Chehab break; 694b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_409FM: 695b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_401: 696b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_403: 697b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_403FM: 698b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_405: 699b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_405FM: 700b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_407: 701b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_407FM: 702b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_409: 703b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_505FM: 704b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_505RDS_MK5: 705b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_505RDS_MK3: 706b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_507_9FM: 707b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_507RDS_MK3: 708b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_507RDS_MK5: 709b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_MANLI; 710b285192aSMauro Carvalho Chehab mask_keycode = 0x003f00; 711b285192aSMauro Carvalho Chehab mask_keyup = 0x004000; 712b285192aSMauro Carvalho Chehab polling = 50; /* ms */ 713b285192aSMauro Carvalho Chehab break; 714b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: 715b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_BEHOLD_COLUMBUS; 716b285192aSMauro Carvalho Chehab mask_keycode = 0x003f00; 717b285192aSMauro Carvalho Chehab mask_keyup = 0x004000; 718b285192aSMauro Carvalho Chehab polling = 50; // ms 719b285192aSMauro Carvalho Chehab break; 720b285192aSMauro Carvalho Chehab case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS: 721b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_PCTV_SEDNA; 722b285192aSMauro Carvalho Chehab mask_keycode = 0x001f00; 723b285192aSMauro Carvalho Chehab mask_keyup = 0x004000; 724b285192aSMauro Carvalho Chehab polling = 50; // ms 725b285192aSMauro Carvalho Chehab break; 726b285192aSMauro Carvalho Chehab case SAA7134_BOARD_GOTVIEW_7135: 727b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_GOTVIEW7135; 728b285192aSMauro Carvalho Chehab mask_keycode = 0x0003CC; 729b285192aSMauro Carvalho Chehab mask_keydown = 0x000010; 730b285192aSMauro Carvalho Chehab polling = 5; /* ms */ 731b285192aSMauro Carvalho Chehab /* GPIO stuff moved to __saa7134_ir_start() */ 732b285192aSMauro Carvalho Chehab break; 733b285192aSMauro Carvalho Chehab case SAA7134_BOARD_VIDEOMATE_TV_PVR: 734b285192aSMauro Carvalho Chehab case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS: 735b285192aSMauro Carvalho Chehab case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII: 736b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_VIDEOMATE_TV_PVR; 737b285192aSMauro Carvalho Chehab mask_keycode = 0x00003F; 738b285192aSMauro Carvalho Chehab mask_keyup = 0x400000; 739b285192aSMauro Carvalho Chehab polling = 50; // ms 740b285192aSMauro Carvalho Chehab break; 741b285192aSMauro Carvalho Chehab case SAA7134_BOARD_PROTEUS_2309: 742b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_PROTEUS_2309; 743b285192aSMauro Carvalho Chehab mask_keycode = 0x00007F; 744b285192aSMauro Carvalho Chehab mask_keyup = 0x000080; 745b285192aSMauro Carvalho Chehab polling = 50; // ms 746b285192aSMauro Carvalho Chehab break; 747b285192aSMauro Carvalho Chehab case SAA7134_BOARD_VIDEOMATE_DVBT_300: 748b285192aSMauro Carvalho Chehab case SAA7134_BOARD_VIDEOMATE_DVBT_200: 749b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_VIDEOMATE_TV_PVR; 750b285192aSMauro Carvalho Chehab mask_keycode = 0x003F00; 751b285192aSMauro Carvalho Chehab mask_keyup = 0x040000; 752b285192aSMauro Carvalho Chehab break; 753b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYDVBS_LR300: 754b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYDVBT_LR301: 755b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYDVBTDUO: 756b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_FLYDVB; 757b285192aSMauro Carvalho Chehab mask_keycode = 0x0001F00; 758b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; 759b285192aSMauro Carvalho Chehab break; 760b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ASUSTeK_P7131_DUAL: 761b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: 762b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ASUSTeK_P7131_ANALOG: 763b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_ASUS_PC39; 764b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ 765b285192aSMauro Carvalho Chehab mask_keyup = 0x0040000; 766b285192aSMauro Carvalho Chehab mask_keycode = 0xffff; 767b285192aSMauro Carvalho Chehab raw_decode = true; 768b285192aSMauro Carvalho Chehab break; 769b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ASUSTeK_PS3_100: 770b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_ASUS_PS3_100; 771b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; 772b285192aSMauro Carvalho Chehab mask_keyup = 0x0040000; 773b285192aSMauro Carvalho Chehab mask_keycode = 0xffff; 774b285192aSMauro Carvalho Chehab raw_decode = true; 775b285192aSMauro Carvalho Chehab break; 776b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ENCORE_ENLTV: 777b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ENCORE_ENLTV_FM: 778b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_ENCORE_ENLTV; 779b285192aSMauro Carvalho Chehab mask_keycode = 0x00007f; 780b285192aSMauro Carvalho Chehab mask_keyup = 0x040000; 781b285192aSMauro Carvalho Chehab polling = 50; // ms 782b285192aSMauro Carvalho Chehab break; 783b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ENCORE_ENLTV_FM53: 784b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ENCORE_ENLTV_FM3: 785b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_ENCORE_ENLTV_FM53; 786b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ 787b285192aSMauro Carvalho Chehab mask_keyup = 0x0040000; 788b285192aSMauro Carvalho Chehab mask_keycode = 0xffff; 789b285192aSMauro Carvalho Chehab raw_decode = true; 790b285192aSMauro Carvalho Chehab break; 791b285192aSMauro Carvalho Chehab case SAA7134_BOARD_10MOONSTVMASTER3: 792b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_ENCORE_ENLTV; 793b285192aSMauro Carvalho Chehab mask_keycode = 0x5f80000; 794b285192aSMauro Carvalho Chehab mask_keyup = 0x8000000; 795b285192aSMauro Carvalho Chehab polling = 50; //ms 796b285192aSMauro Carvalho Chehab break; 797b285192aSMauro Carvalho Chehab case SAA7134_BOARD_GENIUS_TVGO_A11MCE: 798b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_GENIUS_TVGO_A11MCE; 799b285192aSMauro Carvalho Chehab mask_keycode = 0xff; 800b285192aSMauro Carvalho Chehab mask_keydown = 0xf00000; 801b285192aSMauro Carvalho Chehab polling = 50; /* ms */ 802b285192aSMauro Carvalho Chehab break; 803b285192aSMauro Carvalho Chehab case SAA7134_BOARD_REAL_ANGEL_220: 804b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_REAL_AUDIO_220_32_KEYS; 805b285192aSMauro Carvalho Chehab mask_keycode = 0x3f00; 806b285192aSMauro Carvalho Chehab mask_keyup = 0x4000; 807b285192aSMauro Carvalho Chehab polling = 50; /* ms */ 808b285192aSMauro Carvalho Chehab break; 809b285192aSMauro Carvalho Chehab case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG: 810b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_KWORLD_PLUS_TV_ANALOG; 811b285192aSMauro Carvalho Chehab mask_keycode = 0x7f; 812b285192aSMauro Carvalho Chehab polling = 40; /* ms */ 813b285192aSMauro Carvalho Chehab break; 814b285192aSMauro Carvalho Chehab case SAA7134_BOARD_VIDEOMATE_S350: 815b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_VIDEOMATE_S350; 816b285192aSMauro Carvalho Chehab mask_keycode = 0x003f00; 817b285192aSMauro Carvalho Chehab mask_keydown = 0x040000; 818b285192aSMauro Carvalho Chehab break; 819b285192aSMauro Carvalho Chehab case SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S: 820b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_WINFAST; 821b285192aSMauro Carvalho Chehab mask_keycode = 0x5f00; 822b285192aSMauro Carvalho Chehab mask_keyup = 0x020000; 823b285192aSMauro Carvalho Chehab polling = 50; /* ms */ 824b285192aSMauro Carvalho Chehab break; 825b285192aSMauro Carvalho Chehab case SAA7134_BOARD_VIDEOMATE_M1F: 826b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_VIDEOMATE_K100; 827b285192aSMauro Carvalho Chehab mask_keycode = 0x0ff00; 828b285192aSMauro Carvalho Chehab mask_keyup = 0x040000; 829b285192aSMauro Carvalho Chehab break; 830b285192aSMauro Carvalho Chehab case SAA7134_BOARD_HAUPPAUGE_HVR1150: 831b285192aSMauro Carvalho Chehab case SAA7134_BOARD_HAUPPAUGE_HVR1120: 832b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_HAUPPAUGE; 833b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ 834b285192aSMauro Carvalho Chehab mask_keyup = 0x0040000; 835b285192aSMauro Carvalho Chehab mask_keycode = 0xffff; 836b285192aSMauro Carvalho Chehab raw_decode = true; 837b285192aSMauro Carvalho Chehab break; 838b285192aSMauro Carvalho Chehab } 839b285192aSMauro Carvalho Chehab if (NULL == ir_codes) { 8402bb3e2eeSMauro Carvalho Chehab pr_err("Oops: IR config error [card=%d]\n", dev->board); 841b285192aSMauro Carvalho Chehab return -ENODEV; 842b285192aSMauro Carvalho Chehab } 843b285192aSMauro Carvalho Chehab 844b285192aSMauro Carvalho Chehab ir = kzalloc(sizeof(*ir), GFP_KERNEL); 845b285192aSMauro Carvalho Chehab rc = rc_allocate_device(); 846b285192aSMauro Carvalho Chehab if (!ir || !rc) { 847b285192aSMauro Carvalho Chehab err = -ENOMEM; 848b285192aSMauro Carvalho Chehab goto err_out_free; 849b285192aSMauro Carvalho Chehab } 850b285192aSMauro Carvalho Chehab 851b285192aSMauro Carvalho Chehab ir->dev = rc; 852b285192aSMauro Carvalho Chehab dev->remote = ir; 853b285192aSMauro Carvalho Chehab 854b285192aSMauro Carvalho Chehab /* init hardware-specific stuff */ 855b285192aSMauro Carvalho Chehab ir->mask_keycode = mask_keycode; 856b285192aSMauro Carvalho Chehab ir->mask_keydown = mask_keydown; 857b285192aSMauro Carvalho Chehab ir->mask_keyup = mask_keyup; 858b285192aSMauro Carvalho Chehab ir->polling = polling; 859b285192aSMauro Carvalho Chehab ir->raw_decode = raw_decode; 860b285192aSMauro Carvalho Chehab 861b285192aSMauro Carvalho Chehab /* init input device */ 862b285192aSMauro Carvalho Chehab snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)", 863b285192aSMauro Carvalho Chehab saa7134_boards[dev->board].name); 864b285192aSMauro Carvalho Chehab snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", 865b285192aSMauro Carvalho Chehab pci_name(dev->pci)); 866b285192aSMauro Carvalho Chehab 867b285192aSMauro Carvalho Chehab rc->priv = dev; 868b285192aSMauro Carvalho Chehab rc->open = saa7134_ir_open; 869b285192aSMauro Carvalho Chehab rc->close = saa7134_ir_close; 870b285192aSMauro Carvalho Chehab if (raw_decode) 871b285192aSMauro Carvalho Chehab rc->driver_type = RC_DRIVER_IR_RAW; 872b285192aSMauro Carvalho Chehab 873b285192aSMauro Carvalho Chehab rc->input_name = ir->name; 874b285192aSMauro Carvalho Chehab rc->input_phys = ir->phys; 875b285192aSMauro Carvalho Chehab rc->input_id.bustype = BUS_PCI; 876b285192aSMauro Carvalho Chehab rc->input_id.version = 1; 877b285192aSMauro Carvalho Chehab if (dev->pci->subsystem_vendor) { 878b285192aSMauro Carvalho Chehab rc->input_id.vendor = dev->pci->subsystem_vendor; 879b285192aSMauro Carvalho Chehab rc->input_id.product = dev->pci->subsystem_device; 880b285192aSMauro Carvalho Chehab } else { 881b285192aSMauro Carvalho Chehab rc->input_id.vendor = dev->pci->vendor; 882b285192aSMauro Carvalho Chehab rc->input_id.product = dev->pci->device; 883b285192aSMauro Carvalho Chehab } 884b285192aSMauro Carvalho Chehab rc->dev.parent = &dev->pci->dev; 885b285192aSMauro Carvalho Chehab rc->map_name = ir_codes; 886b285192aSMauro Carvalho Chehab rc->driver_name = MODULE_NAME; 887b285192aSMauro Carvalho Chehab 888b285192aSMauro Carvalho Chehab err = rc_register_device(rc); 889b285192aSMauro Carvalho Chehab if (err) 890b285192aSMauro Carvalho Chehab goto err_out_free; 891b285192aSMauro Carvalho Chehab 892b285192aSMauro Carvalho Chehab return 0; 893b285192aSMauro Carvalho Chehab 894b285192aSMauro Carvalho Chehab err_out_free: 895b285192aSMauro Carvalho Chehab rc_free_device(rc); 896b285192aSMauro Carvalho Chehab dev->remote = NULL; 897b285192aSMauro Carvalho Chehab kfree(ir); 898b285192aSMauro Carvalho Chehab return err; 899b285192aSMauro Carvalho Chehab } 900b285192aSMauro Carvalho Chehab 901b285192aSMauro Carvalho Chehab void saa7134_input_fini(struct saa7134_dev *dev) 902b285192aSMauro Carvalho Chehab { 903b285192aSMauro Carvalho Chehab if (NULL == dev->remote) 904b285192aSMauro Carvalho Chehab return; 905b285192aSMauro Carvalho Chehab 906b285192aSMauro Carvalho Chehab saa7134_ir_stop(dev); 907b285192aSMauro Carvalho Chehab rc_unregister_device(dev->remote->dev); 908b285192aSMauro Carvalho Chehab kfree(dev->remote); 909b285192aSMauro Carvalho Chehab dev->remote = NULL; 910b285192aSMauro Carvalho Chehab } 911b285192aSMauro Carvalho Chehab 912b285192aSMauro Carvalho Chehab void saa7134_probe_i2c_ir(struct saa7134_dev *dev) 913b285192aSMauro Carvalho Chehab { 914b285192aSMauro Carvalho Chehab struct i2c_board_info info; 915b285192aSMauro Carvalho Chehab struct i2c_msg msg_msi = { 916b285192aSMauro Carvalho Chehab .addr = 0x50, 917b285192aSMauro Carvalho Chehab .flags = I2C_M_RD, 918b285192aSMauro Carvalho Chehab .len = 0, 919b285192aSMauro Carvalho Chehab .buf = NULL, 920b285192aSMauro Carvalho Chehab }; 921b285192aSMauro Carvalho Chehab int rc; 922b285192aSMauro Carvalho Chehab 923b285192aSMauro Carvalho Chehab if (disable_ir) { 9246be5b1a1SMauro Carvalho Chehab input_dbg("IR has been disabled, not probing for i2c remote\n"); 925b285192aSMauro Carvalho Chehab return; 926b285192aSMauro Carvalho Chehab } 927b285192aSMauro Carvalho Chehab 928b285192aSMauro Carvalho Chehab memset(&info, 0, sizeof(struct i2c_board_info)); 929b285192aSMauro Carvalho Chehab memset(&dev->init_data, 0, sizeof(dev->init_data)); 930b285192aSMauro Carvalho Chehab strlcpy(info.type, "ir_video", I2C_NAME_SIZE); 931b285192aSMauro Carvalho Chehab 932b285192aSMauro Carvalho Chehab switch (dev->board) { 933b285192aSMauro Carvalho Chehab case SAA7134_BOARD_PINNACLE_PCTV_110i: 934b285192aSMauro Carvalho Chehab case SAA7134_BOARD_PINNACLE_PCTV_310i: 935b285192aSMauro Carvalho Chehab dev->init_data.name = "Pinnacle PCTV"; 936b285192aSMauro Carvalho Chehab if (pinnacle_remote == 0) { 937b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_pinnacle_color; 938b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_PINNACLE_COLOR; 939b285192aSMauro Carvalho Chehab info.addr = 0x47; 940b285192aSMauro Carvalho Chehab } else { 941b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_pinnacle_grey; 942b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_PINNACLE_GREY; 943b285192aSMauro Carvalho Chehab info.addr = 0x47; 944b285192aSMauro Carvalho Chehab } 945b285192aSMauro Carvalho Chehab break; 946b285192aSMauro Carvalho Chehab case SAA7134_BOARD_UPMOST_PURPLE_TV: 947b285192aSMauro Carvalho Chehab dev->init_data.name = "Purple TV"; 948b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_purpletv; 949b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_PURPLETV; 950b285192aSMauro Carvalho Chehab info.addr = 0x7a; 951b285192aSMauro Carvalho Chehab break; 952b285192aSMauro Carvalho Chehab case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS: 953b285192aSMauro Carvalho Chehab dev->init_data.name = "MSI TV@nywhere Plus"; 954b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_msi_tvanywhere_plus; 955b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_MSI_TVANYWHERE_PLUS; 956b285192aSMauro Carvalho Chehab /* 957b285192aSMauro Carvalho Chehab * MSI TV@nyware Plus requires more frequent polling 958b285192aSMauro Carvalho Chehab * otherwise it will miss some keypresses 959b285192aSMauro Carvalho Chehab */ 960b285192aSMauro Carvalho Chehab dev->init_data.polling_interval = 50; 961b285192aSMauro Carvalho Chehab info.addr = 0x30; 962b285192aSMauro Carvalho Chehab /* MSI TV@nywhere Plus controller doesn't seem to 963b285192aSMauro Carvalho Chehab respond to probes unless we read something from 964b285192aSMauro Carvalho Chehab an existing device. Weird... 965b285192aSMauro Carvalho Chehab REVISIT: might no longer be needed */ 966b285192aSMauro Carvalho Chehab rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1); 9676be5b1a1SMauro Carvalho Chehab input_dbg("probe 0x%02x @ %s: %s\n", 968b285192aSMauro Carvalho Chehab msg_msi.addr, dev->i2c_adap.name, 969b285192aSMauro Carvalho Chehab (1 == rc) ? "yes" : "no"); 970b285192aSMauro Carvalho Chehab break; 971b285192aSMauro Carvalho Chehab case SAA7134_BOARD_KWORLD_PC150U: 972b285192aSMauro Carvalho Chehab /* copied and modified from MSI TV@nywhere Plus */ 973b285192aSMauro Carvalho Chehab dev->init_data.name = "Kworld PC150-U"; 974b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_kworld_pc150u; 975b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_KWORLD_PC150U; 976b285192aSMauro Carvalho Chehab info.addr = 0x30; 977b285192aSMauro Carvalho Chehab /* MSI TV@nywhere Plus controller doesn't seem to 978b285192aSMauro Carvalho Chehab respond to probes unless we read something from 979b285192aSMauro Carvalho Chehab an existing device. Weird... 980b285192aSMauro Carvalho Chehab REVISIT: might no longer be needed */ 981b285192aSMauro Carvalho Chehab rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1); 9826be5b1a1SMauro Carvalho Chehab input_dbg("probe 0x%02x @ %s: %s\n", 983b285192aSMauro Carvalho Chehab msg_msi.addr, dev->i2c_adap.name, 984b285192aSMauro Carvalho Chehab (1 == rc) ? "yes" : "no"); 985b285192aSMauro Carvalho Chehab break; 986b285192aSMauro Carvalho Chehab case SAA7134_BOARD_HAUPPAUGE_HVR1110: 987b285192aSMauro Carvalho Chehab dev->init_data.name = "HVR 1110"; 988b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_hvr1110; 989b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_HAUPPAUGE; 990b285192aSMauro Carvalho Chehab info.addr = 0x71; 991b285192aSMauro Carvalho Chehab break; 992b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_607FM_MK3: 993b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_607FM_MK5: 994b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_609FM_MK3: 995b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_609FM_MK5: 996b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_607RDS_MK3: 997b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_607RDS_MK5: 998b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_609RDS_MK3: 999b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_609RDS_MK5: 1000b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_M6: 1001b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_M63: 1002b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_M6_EXTRA: 1003b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_H6: 1004b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_X7: 1005b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_H7: 1006b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_A7: 1007b285192aSMauro Carvalho Chehab dev->init_data.name = "BeholdTV"; 1008b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_beholdm6xx; 1009b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_BEHOLD; 1010c003ab1bSDavid Härdeman dev->init_data.type = RC_BIT_NEC; 1011b285192aSMauro Carvalho Chehab info.addr = 0x2d; 1012b285192aSMauro Carvalho Chehab break; 1013b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_CARDBUS_501: 1014b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: 1015b285192aSMauro Carvalho Chehab info.addr = 0x40; 1016b285192aSMauro Carvalho Chehab break; 101734fe2784SOndrej Zary case SAA7134_BOARD_AVERMEDIA_A706: 101834fe2784SOndrej Zary info.addr = 0x41; 101934fe2784SOndrej Zary break; 1020b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYDVB_TRIO: 1021b285192aSMauro Carvalho Chehab dev->init_data.name = "FlyDVB Trio"; 1022b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_flydvb_trio; 1023b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_FLYDVB; 1024b285192aSMauro Carvalho Chehab info.addr = 0x0b; 1025b285192aSMauro Carvalho Chehab break; 1026b285192aSMauro Carvalho Chehab default: 10276be5b1a1SMauro Carvalho Chehab input_dbg("No I2C IR support for board %x\n", dev->board); 1028b285192aSMauro Carvalho Chehab return; 1029b285192aSMauro Carvalho Chehab } 1030b285192aSMauro Carvalho Chehab 1031b285192aSMauro Carvalho Chehab if (dev->init_data.name) 1032b285192aSMauro Carvalho Chehab info.platform_data = &dev->init_data; 1033b285192aSMauro Carvalho Chehab i2c_new_device(&dev->i2c_adap, &info); 1034b285192aSMauro Carvalho Chehab } 1035b285192aSMauro Carvalho Chehab 1036b285192aSMauro Carvalho Chehab static int saa7134_raw_decode_irq(struct saa7134_dev *dev) 1037b285192aSMauro Carvalho Chehab { 1038b285192aSMauro Carvalho Chehab struct saa7134_card_ir *ir = dev->remote; 1039b285192aSMauro Carvalho Chehab unsigned long timeout; 1040b285192aSMauro Carvalho Chehab int space; 1041b285192aSMauro Carvalho Chehab 1042b285192aSMauro Carvalho Chehab /* Generate initial event */ 1043b285192aSMauro Carvalho Chehab saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 1044b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 1045b285192aSMauro Carvalho Chehab space = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown; 1046b285192aSMauro Carvalho Chehab ir_raw_event_store_edge(dev->remote->dev, space ? IR_SPACE : IR_PULSE); 1047b285192aSMauro Carvalho Chehab 1048b285192aSMauro Carvalho Chehab /* 1049b285192aSMauro Carvalho Chehab * Wait 15 ms from the start of the first IR event before processing 1050b285192aSMauro Carvalho Chehab * the event. This time is enough for NEC protocol. May need adjustments 1051b285192aSMauro Carvalho Chehab * to work with other protocols. 1052b285192aSMauro Carvalho Chehab */ 1053b285192aSMauro Carvalho Chehab smp_mb(); 1054b285192aSMauro Carvalho Chehab 1055b285192aSMauro Carvalho Chehab if (!timer_pending(&ir->timer)) { 1056b285192aSMauro Carvalho Chehab timeout = jiffies + msecs_to_jiffies(15); 1057b285192aSMauro Carvalho Chehab mod_timer(&ir->timer, timeout); 1058b285192aSMauro Carvalho Chehab } 1059b285192aSMauro Carvalho Chehab 1060b285192aSMauro Carvalho Chehab return 1; 1061b285192aSMauro Carvalho Chehab } 1062