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 21b285192aSMauro Carvalho Chehab #include <linux/module.h> 22b285192aSMauro Carvalho Chehab #include <linux/init.h> 23b285192aSMauro Carvalho Chehab #include <linux/delay.h> 24b285192aSMauro Carvalho Chehab #include <linux/interrupt.h> 25b285192aSMauro Carvalho Chehab #include <linux/slab.h> 26b285192aSMauro Carvalho Chehab 27b285192aSMauro Carvalho Chehab #include "saa7134-reg.h" 28b285192aSMauro Carvalho Chehab #include "saa7134.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 44b285192aSMauro Carvalho Chehab #define dprintk(fmt, arg...) if (ir_debug) \ 45b285192aSMauro Carvalho Chehab printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg) 46b285192aSMauro Carvalho Chehab #define i2cdprintk(fmt, arg...) if (ir_debug) \ 47b285192aSMauro Carvalho Chehab printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg) 48b285192aSMauro Carvalho Chehab 49b285192aSMauro Carvalho Chehab /* Helper function for raw decoding at GPIO16 or GPIO18 */ 50b285192aSMauro Carvalho Chehab static int saa7134_raw_decode_irq(struct saa7134_dev *dev); 51b285192aSMauro Carvalho Chehab 52b285192aSMauro Carvalho Chehab /* -------------------- GPIO generic keycode builder -------------------- */ 53b285192aSMauro Carvalho Chehab 54b285192aSMauro Carvalho Chehab static int build_key(struct saa7134_dev *dev) 55b285192aSMauro Carvalho Chehab { 56b285192aSMauro Carvalho Chehab struct saa7134_card_ir *ir = dev->remote; 57b285192aSMauro Carvalho Chehab u32 gpio, data; 58b285192aSMauro Carvalho Chehab 59b285192aSMauro Carvalho Chehab /* here comes the additional handshake steps for some cards */ 60b285192aSMauro Carvalho Chehab switch (dev->board) { 61b285192aSMauro Carvalho Chehab case SAA7134_BOARD_GOTVIEW_7135: 62b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPSTATUS1, 0x80); 63b285192aSMauro Carvalho Chehab saa_clearb(SAA7134_GPIO_GPSTATUS1, 0x80); 64b285192aSMauro Carvalho Chehab break; 65b285192aSMauro Carvalho Chehab } 66b285192aSMauro Carvalho Chehab /* rising SAA7134_GPIO_GPRESCAN reads the status */ 67b285192aSMauro Carvalho Chehab saa_clearb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN); 68b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN); 69b285192aSMauro Carvalho Chehab 70b285192aSMauro Carvalho Chehab gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2); 71b285192aSMauro Carvalho Chehab if (ir->polling) { 72b285192aSMauro Carvalho Chehab if (ir->last_gpio == gpio) 73b285192aSMauro Carvalho Chehab return 0; 74b285192aSMauro Carvalho Chehab ir->last_gpio = gpio; 75b285192aSMauro Carvalho Chehab } 76b285192aSMauro Carvalho Chehab 77b285192aSMauro Carvalho Chehab data = ir_extract_bits(gpio, ir->mask_keycode); 78b285192aSMauro Carvalho Chehab dprintk("build_key gpio=0x%x mask=0x%x data=%d\n", 79b285192aSMauro Carvalho Chehab gpio, ir->mask_keycode, data); 80b285192aSMauro Carvalho Chehab 81b285192aSMauro Carvalho Chehab switch (dev->board) { 82b285192aSMauro Carvalho Chehab case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG: 83b285192aSMauro Carvalho Chehab if (data == ir->mask_keycode) 84b285192aSMauro Carvalho Chehab rc_keyup(ir->dev); 85b285192aSMauro Carvalho Chehab else 86120703f9SDavid Härdeman rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0); 87b285192aSMauro Carvalho Chehab return 0; 88b285192aSMauro Carvalho Chehab } 89b285192aSMauro Carvalho Chehab 90b285192aSMauro Carvalho Chehab if (ir->polling) { 91b285192aSMauro Carvalho Chehab if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) || 92b285192aSMauro Carvalho Chehab (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { 93120703f9SDavid Härdeman rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0); 94b285192aSMauro Carvalho Chehab } else { 95b285192aSMauro Carvalho Chehab rc_keyup(ir->dev); 96b285192aSMauro Carvalho Chehab } 97b285192aSMauro Carvalho Chehab } 98b285192aSMauro Carvalho Chehab else { /* IRQ driven mode - handle key press and release in one go */ 99b285192aSMauro Carvalho Chehab if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) || 100b285192aSMauro Carvalho Chehab (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { 101120703f9SDavid Härdeman rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0); 102b285192aSMauro Carvalho Chehab rc_keyup(ir->dev); 103b285192aSMauro Carvalho Chehab } 104b285192aSMauro Carvalho Chehab } 105b285192aSMauro Carvalho Chehab 106b285192aSMauro Carvalho Chehab return 0; 107b285192aSMauro Carvalho Chehab } 108b285192aSMauro Carvalho Chehab 109b285192aSMauro Carvalho Chehab /* --------------------- Chip specific I2C key builders ----------------- */ 110b285192aSMauro Carvalho Chehab 1114dd9bb91SDavid Härdeman static int get_key_flydvb_trio(struct IR_i2c *ir, enum rc_type *protocol, 1124dd9bb91SDavid Härdeman u32 *scancode, u8 *toggle) 113b285192aSMauro Carvalho Chehab { 114b285192aSMauro Carvalho Chehab int gpio; 115b285192aSMauro Carvalho Chehab int attempt = 0; 116b285192aSMauro Carvalho Chehab unsigned char b; 117b285192aSMauro Carvalho Chehab 118b285192aSMauro Carvalho Chehab /* We need this to access GPI Used by the saa_readl macro. */ 119b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = ir->c->adapter->algo_data; 120b285192aSMauro Carvalho Chehab 121b285192aSMauro Carvalho Chehab if (dev == NULL) { 122b285192aSMauro Carvalho Chehab i2cdprintk("get_key_flydvb_trio: " 123b285192aSMauro Carvalho Chehab "ir->c->adapter->algo_data is NULL!\n"); 124b285192aSMauro Carvalho Chehab return -EIO; 125b285192aSMauro Carvalho Chehab } 126b285192aSMauro Carvalho Chehab 127b285192aSMauro Carvalho Chehab /* rising SAA7134_GPIGPRESCAN reads the status */ 128b285192aSMauro Carvalho Chehab saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 129b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 130b285192aSMauro Carvalho Chehab 131b285192aSMauro Carvalho Chehab gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2); 132b285192aSMauro Carvalho Chehab 133b285192aSMauro Carvalho Chehab if (0x40000 & ~gpio) 134b285192aSMauro Carvalho Chehab return 0; /* No button press */ 135b285192aSMauro Carvalho Chehab 136b285192aSMauro Carvalho Chehab /* No button press - only before first key pressed */ 137b285192aSMauro Carvalho Chehab if (b == 0xFF) 138b285192aSMauro Carvalho Chehab return 0; 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 } 153b285192aSMauro Carvalho Chehab i2cdprintk("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)) { 158b285192aSMauro Carvalho Chehab i2cdprintk("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) { 177b285192aSMauro Carvalho Chehab i2cdprintk("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)) { 198b285192aSMauro Carvalho Chehab i2cdprintk("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 209b285192aSMauro Carvalho Chehab dprintk("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) { 226b285192aSMauro Carvalho Chehab i2cdprintk("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)) { 247b285192aSMauro Carvalho Chehab i2cdprintk("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 258b285192aSMauro Carvalho Chehab dprintk("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)) { 272b285192aSMauro Carvalho Chehab i2cdprintk("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)) { 341b285192aSMauro Carvalho Chehab i2cdprintk("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; 3494dd9bb91SDavid Härdeman *scancode = RC_SCANCODE_NECX(((data[10] << 8) | data[11]), 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)) { 366b285192aSMauro Carvalho Chehab i2cdprintk("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 398b285192aSMauro Carvalho Chehab i2cdprintk("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: 488b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_305: 489b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_505: 490b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_307: 491b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_507: 492b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_507UA: 493b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_GO_007_FM: 494b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_M102: 495b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS: 496b285192aSMauro Carvalho Chehab /* Without this we won't receive key up events */ 497b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE0, 0x4); 498b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); 499b285192aSMauro Carvalho Chehab break; 500b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_777: 501b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_A16AR: 502b285192aSMauro Carvalho Chehab /* Without this we won't receive key up events */ 503b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE1, 0x1); 504b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1); 505b285192aSMauro Carvalho Chehab break; 506b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_A16D: 507b285192aSMauro Carvalho Chehab /* Without this we won't receive key up events */ 508b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE1, 0x1); 509b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1); 510b285192aSMauro Carvalho Chehab break; 511b285192aSMauro Carvalho Chehab case SAA7134_BOARD_GOTVIEW_7135: 512b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE1, 0x80); 513b285192aSMauro Carvalho Chehab break; 514b285192aSMauro Carvalho Chehab } 515b285192aSMauro Carvalho Chehab 516b285192aSMauro Carvalho Chehab ir->running = true; 517b285192aSMauro Carvalho Chehab 518b285192aSMauro Carvalho Chehab if (ir->polling) { 519b285192aSMauro Carvalho Chehab setup_timer(&ir->timer, saa7134_input_timer, 520b285192aSMauro Carvalho Chehab (unsigned long)dev); 521b285192aSMauro Carvalho Chehab ir->timer.expires = jiffies + HZ; 522b285192aSMauro Carvalho Chehab add_timer(&ir->timer); 523b285192aSMauro Carvalho Chehab } else if (ir->raw_decode) { 524b285192aSMauro Carvalho Chehab /* set timer_end for code completion */ 525b285192aSMauro Carvalho Chehab setup_timer(&ir->timer, ir_raw_decode_timer_end, 526b285192aSMauro Carvalho Chehab (unsigned long)dev); 527b285192aSMauro Carvalho Chehab } 528b285192aSMauro Carvalho Chehab 529b285192aSMauro Carvalho Chehab return 0; 530b285192aSMauro Carvalho Chehab } 531b285192aSMauro Carvalho Chehab 532b285192aSMauro Carvalho Chehab static void __saa7134_ir_stop(void *priv) 533b285192aSMauro Carvalho Chehab { 534b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = priv; 535b285192aSMauro Carvalho Chehab struct saa7134_card_ir *ir; 536b285192aSMauro Carvalho Chehab 537b285192aSMauro Carvalho Chehab if (!dev || !dev->remote) 538b285192aSMauro Carvalho Chehab return; 539b285192aSMauro Carvalho Chehab 540b285192aSMauro Carvalho Chehab ir = dev->remote; 541b285192aSMauro Carvalho Chehab if (!ir->running) 542b285192aSMauro Carvalho Chehab return; 543b285192aSMauro Carvalho Chehab 544b285192aSMauro Carvalho Chehab if (ir->polling || ir->raw_decode) 545b285192aSMauro Carvalho Chehab del_timer_sync(&ir->timer); 546b285192aSMauro Carvalho Chehab 547b285192aSMauro Carvalho Chehab ir->running = false; 548b285192aSMauro Carvalho Chehab 549b285192aSMauro Carvalho Chehab return; 550b285192aSMauro Carvalho Chehab } 551b285192aSMauro Carvalho Chehab 552b285192aSMauro Carvalho Chehab int saa7134_ir_start(struct saa7134_dev *dev) 553b285192aSMauro Carvalho Chehab { 554b285192aSMauro Carvalho Chehab if (dev->remote->users) 555b285192aSMauro Carvalho Chehab return __saa7134_ir_start(dev); 556b285192aSMauro Carvalho Chehab 557b285192aSMauro Carvalho Chehab return 0; 558b285192aSMauro Carvalho Chehab } 559b285192aSMauro Carvalho Chehab 560b285192aSMauro Carvalho Chehab void saa7134_ir_stop(struct saa7134_dev *dev) 561b285192aSMauro Carvalho Chehab { 562b285192aSMauro Carvalho Chehab if (dev->remote->users) 563b285192aSMauro Carvalho Chehab __saa7134_ir_stop(dev); 564b285192aSMauro Carvalho Chehab } 565b285192aSMauro Carvalho Chehab 566b285192aSMauro Carvalho Chehab static int saa7134_ir_open(struct rc_dev *rc) 567b285192aSMauro Carvalho Chehab { 568b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = rc->priv; 569b285192aSMauro Carvalho Chehab 570b285192aSMauro Carvalho Chehab dev->remote->users++; 571b285192aSMauro Carvalho Chehab return __saa7134_ir_start(dev); 572b285192aSMauro Carvalho Chehab } 573b285192aSMauro Carvalho Chehab 574b285192aSMauro Carvalho Chehab static void saa7134_ir_close(struct rc_dev *rc) 575b285192aSMauro Carvalho Chehab { 576b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = rc->priv; 577b285192aSMauro Carvalho Chehab 578b285192aSMauro Carvalho Chehab dev->remote->users--; 579b285192aSMauro Carvalho Chehab if (!dev->remote->users) 580b285192aSMauro Carvalho Chehab __saa7134_ir_stop(dev); 581b285192aSMauro Carvalho Chehab } 582b285192aSMauro Carvalho Chehab 583b285192aSMauro Carvalho Chehab int saa7134_input_init1(struct saa7134_dev *dev) 584b285192aSMauro Carvalho Chehab { 585b285192aSMauro Carvalho Chehab struct saa7134_card_ir *ir; 586b285192aSMauro Carvalho Chehab struct rc_dev *rc; 587b285192aSMauro Carvalho Chehab char *ir_codes = NULL; 588b285192aSMauro Carvalho Chehab u32 mask_keycode = 0; 589b285192aSMauro Carvalho Chehab u32 mask_keydown = 0; 590b285192aSMauro Carvalho Chehab u32 mask_keyup = 0; 591b285192aSMauro Carvalho Chehab unsigned polling = 0; 592b285192aSMauro Carvalho Chehab bool raw_decode = false; 593b285192aSMauro Carvalho Chehab int err; 594b285192aSMauro Carvalho Chehab 595b285192aSMauro Carvalho Chehab if (dev->has_remote != SAA7134_REMOTE_GPIO) 596b285192aSMauro Carvalho Chehab return -ENODEV; 597b285192aSMauro Carvalho Chehab if (disable_ir) 598b285192aSMauro Carvalho Chehab return -ENODEV; 599b285192aSMauro Carvalho Chehab 600b285192aSMauro Carvalho Chehab /* detect & configure */ 601b285192aSMauro Carvalho Chehab switch (dev->board) { 602b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYVIDEO2000: 603b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYVIDEO3000: 604b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYTVPLATINUM_FM: 605b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYTVPLATINUM_MINI2: 606b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM: 607b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_FLYVIDEO; 608b285192aSMauro Carvalho Chehab mask_keycode = 0xEC00000; 609b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; 610b285192aSMauro Carvalho Chehab break; 611b285192aSMauro Carvalho Chehab case SAA7134_BOARD_CINERGY400: 612b285192aSMauro Carvalho Chehab case SAA7134_BOARD_CINERGY600: 613b285192aSMauro Carvalho Chehab case SAA7134_BOARD_CINERGY600_MK3: 614b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_CINERGY; 615b285192aSMauro Carvalho Chehab mask_keycode = 0x00003f; 616b285192aSMauro Carvalho Chehab mask_keyup = 0x040000; 617b285192aSMauro Carvalho Chehab break; 618b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ECS_TVP3XP: 619b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ECS_TVP3XP_4CB5: 620b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_EZTV; 621b285192aSMauro Carvalho Chehab mask_keycode = 0x00017c; 622b285192aSMauro Carvalho Chehab mask_keyup = 0x000002; 623b285192aSMauro Carvalho Chehab polling = 50; // ms 624b285192aSMauro Carvalho Chehab break; 625b285192aSMauro Carvalho Chehab case SAA7134_BOARD_KWORLD_XPERT: 626b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVACSSMARTTV: 627b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_PIXELVIEW; 628b285192aSMauro Carvalho Chehab mask_keycode = 0x00001F; 629b285192aSMauro Carvalho Chehab mask_keyup = 0x000020; 630b285192aSMauro Carvalho Chehab polling = 50; // ms 631b285192aSMauro Carvalho Chehab break; 632b285192aSMauro Carvalho Chehab case SAA7134_BOARD_MD2819: 633b285192aSMauro Carvalho Chehab case SAA7134_BOARD_KWORLD_VSTREAM_XPERT: 634b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_305: 635b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_307: 636b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_305: 637b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_505: 638b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_307: 639b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_507: 640b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_507UA: 641b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_GO_007_FM: 642b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_M102: 643b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS: 644b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_AVERMEDIA; 645b285192aSMauro Carvalho Chehab mask_keycode = 0x0007C8; 646b285192aSMauro Carvalho Chehab mask_keydown = 0x000010; 647b285192aSMauro Carvalho Chehab polling = 50; // ms 648b285192aSMauro Carvalho Chehab /* GPIO stuff moved to __saa7134_ir_start() */ 649b285192aSMauro Carvalho Chehab break; 650b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_M135A: 651b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_AVERMEDIA_M135A; 652b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ 653b285192aSMauro Carvalho Chehab mask_keyup = 0x0040000; 654b285192aSMauro Carvalho Chehab mask_keycode = 0xffff; 655b285192aSMauro Carvalho Chehab raw_decode = true; 656b285192aSMauro Carvalho Chehab break; 657b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_M733A: 658b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_AVERMEDIA_M733A_RM_K6; 659b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; 660b285192aSMauro Carvalho Chehab mask_keyup = 0x0040000; 661b285192aSMauro Carvalho Chehab mask_keycode = 0xffff; 662b285192aSMauro Carvalho Chehab raw_decode = true; 663b285192aSMauro Carvalho Chehab break; 664b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_777: 665b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_A16AR: 666b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_AVERMEDIA; 667b285192aSMauro Carvalho Chehab mask_keycode = 0x02F200; 668b285192aSMauro Carvalho Chehab mask_keydown = 0x000400; 669b285192aSMauro Carvalho Chehab polling = 50; // ms 670b285192aSMauro Carvalho Chehab /* GPIO stuff moved to __saa7134_ir_start() */ 671b285192aSMauro Carvalho Chehab break; 672b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_A16D: 673b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_AVERMEDIA_A16D; 674b285192aSMauro Carvalho Chehab mask_keycode = 0x02F200; 675b285192aSMauro Carvalho Chehab mask_keydown = 0x000400; 676b285192aSMauro Carvalho Chehab polling = 50; /* ms */ 677b285192aSMauro Carvalho Chehab /* GPIO stuff moved to __saa7134_ir_start() */ 678b285192aSMauro Carvalho Chehab break; 679b285192aSMauro Carvalho Chehab case SAA7134_BOARD_KWORLD_TERMINATOR: 680b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_PIXELVIEW; 681b285192aSMauro Carvalho Chehab mask_keycode = 0x00001f; 682b285192aSMauro Carvalho Chehab mask_keyup = 0x000060; 683b285192aSMauro Carvalho Chehab polling = 50; // ms 684b285192aSMauro Carvalho Chehab break; 685b285192aSMauro Carvalho Chehab case SAA7134_BOARD_MANLI_MTV001: 686b285192aSMauro Carvalho Chehab case SAA7134_BOARD_MANLI_MTV002: 687b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_MANLI; 688b285192aSMauro Carvalho Chehab mask_keycode = 0x001f00; 689b285192aSMauro Carvalho Chehab mask_keyup = 0x004000; 690b285192aSMauro Carvalho Chehab polling = 50; /* ms */ 691b285192aSMauro Carvalho Chehab break; 692b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_409FM: 693b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_401: 694b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_403: 695b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_403FM: 696b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_405: 697b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_405FM: 698b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_407: 699b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_407FM: 700b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_409: 701b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_505FM: 702b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_505RDS_MK5: 703b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_505RDS_MK3: 704b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_507_9FM: 705b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_507RDS_MK3: 706b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_507RDS_MK5: 707b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_MANLI; 708b285192aSMauro Carvalho Chehab mask_keycode = 0x003f00; 709b285192aSMauro Carvalho Chehab mask_keyup = 0x004000; 710b285192aSMauro Carvalho Chehab polling = 50; /* ms */ 711b285192aSMauro Carvalho Chehab break; 712b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: 713b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_BEHOLD_COLUMBUS; 714b285192aSMauro Carvalho Chehab mask_keycode = 0x003f00; 715b285192aSMauro Carvalho Chehab mask_keyup = 0x004000; 716b285192aSMauro Carvalho Chehab polling = 50; // ms 717b285192aSMauro Carvalho Chehab break; 718b285192aSMauro Carvalho Chehab case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS: 719b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_PCTV_SEDNA; 720b285192aSMauro Carvalho Chehab mask_keycode = 0x001f00; 721b285192aSMauro Carvalho Chehab mask_keyup = 0x004000; 722b285192aSMauro Carvalho Chehab polling = 50; // ms 723b285192aSMauro Carvalho Chehab break; 724b285192aSMauro Carvalho Chehab case SAA7134_BOARD_GOTVIEW_7135: 725b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_GOTVIEW7135; 726b285192aSMauro Carvalho Chehab mask_keycode = 0x0003CC; 727b285192aSMauro Carvalho Chehab mask_keydown = 0x000010; 728b285192aSMauro Carvalho Chehab polling = 5; /* ms */ 729b285192aSMauro Carvalho Chehab /* GPIO stuff moved to __saa7134_ir_start() */ 730b285192aSMauro Carvalho Chehab break; 731b285192aSMauro Carvalho Chehab case SAA7134_BOARD_VIDEOMATE_TV_PVR: 732b285192aSMauro Carvalho Chehab case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS: 733b285192aSMauro Carvalho Chehab case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII: 734b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_VIDEOMATE_TV_PVR; 735b285192aSMauro Carvalho Chehab mask_keycode = 0x00003F; 736b285192aSMauro Carvalho Chehab mask_keyup = 0x400000; 737b285192aSMauro Carvalho Chehab polling = 50; // ms 738b285192aSMauro Carvalho Chehab break; 739b285192aSMauro Carvalho Chehab case SAA7134_BOARD_PROTEUS_2309: 740b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_PROTEUS_2309; 741b285192aSMauro Carvalho Chehab mask_keycode = 0x00007F; 742b285192aSMauro Carvalho Chehab mask_keyup = 0x000080; 743b285192aSMauro Carvalho Chehab polling = 50; // ms 744b285192aSMauro Carvalho Chehab break; 745b285192aSMauro Carvalho Chehab case SAA7134_BOARD_VIDEOMATE_DVBT_300: 746b285192aSMauro Carvalho Chehab case SAA7134_BOARD_VIDEOMATE_DVBT_200: 747b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_VIDEOMATE_TV_PVR; 748b285192aSMauro Carvalho Chehab mask_keycode = 0x003F00; 749b285192aSMauro Carvalho Chehab mask_keyup = 0x040000; 750b285192aSMauro Carvalho Chehab break; 751b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYDVBS_LR300: 752b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYDVBT_LR301: 753b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYDVBTDUO: 754b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_FLYDVB; 755b285192aSMauro Carvalho Chehab mask_keycode = 0x0001F00; 756b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; 757b285192aSMauro Carvalho Chehab break; 758b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ASUSTeK_P7131_DUAL: 759b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: 760b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ASUSTeK_P7131_ANALOG: 761b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_ASUS_PC39; 762b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ 763b285192aSMauro Carvalho Chehab mask_keyup = 0x0040000; 764b285192aSMauro Carvalho Chehab mask_keycode = 0xffff; 765b285192aSMauro Carvalho Chehab raw_decode = true; 766b285192aSMauro Carvalho Chehab break; 767b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ASUSTeK_PS3_100: 768b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_ASUS_PS3_100; 769b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; 770b285192aSMauro Carvalho Chehab mask_keyup = 0x0040000; 771b285192aSMauro Carvalho Chehab mask_keycode = 0xffff; 772b285192aSMauro Carvalho Chehab raw_decode = true; 773b285192aSMauro Carvalho Chehab break; 774b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ENCORE_ENLTV: 775b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ENCORE_ENLTV_FM: 776b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_ENCORE_ENLTV; 777b285192aSMauro Carvalho Chehab mask_keycode = 0x00007f; 778b285192aSMauro Carvalho Chehab mask_keyup = 0x040000; 779b285192aSMauro Carvalho Chehab polling = 50; // ms 780b285192aSMauro Carvalho Chehab break; 781b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ENCORE_ENLTV_FM53: 782b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ENCORE_ENLTV_FM3: 783b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_ENCORE_ENLTV_FM53; 784b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ 785b285192aSMauro Carvalho Chehab mask_keyup = 0x0040000; 786b285192aSMauro Carvalho Chehab mask_keycode = 0xffff; 787b285192aSMauro Carvalho Chehab raw_decode = true; 788b285192aSMauro Carvalho Chehab break; 789b285192aSMauro Carvalho Chehab case SAA7134_BOARD_10MOONSTVMASTER3: 790b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_ENCORE_ENLTV; 791b285192aSMauro Carvalho Chehab mask_keycode = 0x5f80000; 792b285192aSMauro Carvalho Chehab mask_keyup = 0x8000000; 793b285192aSMauro Carvalho Chehab polling = 50; //ms 794b285192aSMauro Carvalho Chehab break; 795b285192aSMauro Carvalho Chehab case SAA7134_BOARD_GENIUS_TVGO_A11MCE: 796b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_GENIUS_TVGO_A11MCE; 797b285192aSMauro Carvalho Chehab mask_keycode = 0xff; 798b285192aSMauro Carvalho Chehab mask_keydown = 0xf00000; 799b285192aSMauro Carvalho Chehab polling = 50; /* ms */ 800b285192aSMauro Carvalho Chehab break; 801b285192aSMauro Carvalho Chehab case SAA7134_BOARD_REAL_ANGEL_220: 802b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_REAL_AUDIO_220_32_KEYS; 803b285192aSMauro Carvalho Chehab mask_keycode = 0x3f00; 804b285192aSMauro Carvalho Chehab mask_keyup = 0x4000; 805b285192aSMauro Carvalho Chehab polling = 50; /* ms */ 806b285192aSMauro Carvalho Chehab break; 807b285192aSMauro Carvalho Chehab case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG: 808b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_KWORLD_PLUS_TV_ANALOG; 809b285192aSMauro Carvalho Chehab mask_keycode = 0x7f; 810b285192aSMauro Carvalho Chehab polling = 40; /* ms */ 811b285192aSMauro Carvalho Chehab break; 812b285192aSMauro Carvalho Chehab case SAA7134_BOARD_VIDEOMATE_S350: 813b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_VIDEOMATE_S350; 814b285192aSMauro Carvalho Chehab mask_keycode = 0x003f00; 815b285192aSMauro Carvalho Chehab mask_keydown = 0x040000; 816b285192aSMauro Carvalho Chehab break; 817b285192aSMauro Carvalho Chehab case SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S: 818b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_WINFAST; 819b285192aSMauro Carvalho Chehab mask_keycode = 0x5f00; 820b285192aSMauro Carvalho Chehab mask_keyup = 0x020000; 821b285192aSMauro Carvalho Chehab polling = 50; /* ms */ 822b285192aSMauro Carvalho Chehab break; 823b285192aSMauro Carvalho Chehab case SAA7134_BOARD_VIDEOMATE_M1F: 824b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_VIDEOMATE_K100; 825b285192aSMauro Carvalho Chehab mask_keycode = 0x0ff00; 826b285192aSMauro Carvalho Chehab mask_keyup = 0x040000; 827b285192aSMauro Carvalho Chehab break; 828b285192aSMauro Carvalho Chehab case SAA7134_BOARD_HAUPPAUGE_HVR1150: 829b285192aSMauro Carvalho Chehab case SAA7134_BOARD_HAUPPAUGE_HVR1120: 830b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_HAUPPAUGE; 831b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ 832b285192aSMauro Carvalho Chehab mask_keyup = 0x0040000; 833b285192aSMauro Carvalho Chehab mask_keycode = 0xffff; 834b285192aSMauro Carvalho Chehab raw_decode = true; 835b285192aSMauro Carvalho Chehab break; 836b285192aSMauro Carvalho Chehab } 837b285192aSMauro Carvalho Chehab if (NULL == ir_codes) { 838b285192aSMauro Carvalho Chehab printk("%s: Oops: IR config error [card=%d]\n", 839b285192aSMauro Carvalho Chehab dev->name, dev->board); 840b285192aSMauro Carvalho Chehab return -ENODEV; 841b285192aSMauro Carvalho Chehab } 842b285192aSMauro Carvalho Chehab 843b285192aSMauro Carvalho Chehab ir = kzalloc(sizeof(*ir), GFP_KERNEL); 844b285192aSMauro Carvalho Chehab rc = rc_allocate_device(); 845b285192aSMauro Carvalho Chehab if (!ir || !rc) { 846b285192aSMauro Carvalho Chehab err = -ENOMEM; 847b285192aSMauro Carvalho Chehab goto err_out_free; 848b285192aSMauro Carvalho Chehab } 849b285192aSMauro Carvalho Chehab 850b285192aSMauro Carvalho Chehab ir->dev = rc; 851b285192aSMauro Carvalho Chehab dev->remote = ir; 852b285192aSMauro Carvalho Chehab 853b285192aSMauro Carvalho Chehab /* init hardware-specific stuff */ 854b285192aSMauro Carvalho Chehab ir->mask_keycode = mask_keycode; 855b285192aSMauro Carvalho Chehab ir->mask_keydown = mask_keydown; 856b285192aSMauro Carvalho Chehab ir->mask_keyup = mask_keyup; 857b285192aSMauro Carvalho Chehab ir->polling = polling; 858b285192aSMauro Carvalho Chehab ir->raw_decode = raw_decode; 859b285192aSMauro Carvalho Chehab 860b285192aSMauro Carvalho Chehab /* init input device */ 861b285192aSMauro Carvalho Chehab snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)", 862b285192aSMauro Carvalho Chehab saa7134_boards[dev->board].name); 863b285192aSMauro Carvalho Chehab snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", 864b285192aSMauro Carvalho Chehab pci_name(dev->pci)); 865b285192aSMauro Carvalho Chehab 866b285192aSMauro Carvalho Chehab rc->priv = dev; 867b285192aSMauro Carvalho Chehab rc->open = saa7134_ir_open; 868b285192aSMauro Carvalho Chehab rc->close = saa7134_ir_close; 869b285192aSMauro Carvalho Chehab if (raw_decode) 870b285192aSMauro Carvalho Chehab rc->driver_type = RC_DRIVER_IR_RAW; 871b285192aSMauro Carvalho Chehab 872b285192aSMauro Carvalho Chehab rc->input_name = ir->name; 873b285192aSMauro Carvalho Chehab rc->input_phys = ir->phys; 874b285192aSMauro Carvalho Chehab rc->input_id.bustype = BUS_PCI; 875b285192aSMauro Carvalho Chehab rc->input_id.version = 1; 876b285192aSMauro Carvalho Chehab if (dev->pci->subsystem_vendor) { 877b285192aSMauro Carvalho Chehab rc->input_id.vendor = dev->pci->subsystem_vendor; 878b285192aSMauro Carvalho Chehab rc->input_id.product = dev->pci->subsystem_device; 879b285192aSMauro Carvalho Chehab } else { 880b285192aSMauro Carvalho Chehab rc->input_id.vendor = dev->pci->vendor; 881b285192aSMauro Carvalho Chehab rc->input_id.product = dev->pci->device; 882b285192aSMauro Carvalho Chehab } 883b285192aSMauro Carvalho Chehab rc->dev.parent = &dev->pci->dev; 884b285192aSMauro Carvalho Chehab rc->map_name = ir_codes; 885b285192aSMauro Carvalho Chehab rc->driver_name = MODULE_NAME; 886b285192aSMauro Carvalho Chehab 887b285192aSMauro Carvalho Chehab err = rc_register_device(rc); 888b285192aSMauro Carvalho Chehab if (err) 889b285192aSMauro Carvalho Chehab goto err_out_free; 890b285192aSMauro Carvalho Chehab 891b285192aSMauro Carvalho Chehab return 0; 892b285192aSMauro Carvalho Chehab 893b285192aSMauro Carvalho Chehab err_out_free: 894b285192aSMauro Carvalho Chehab rc_free_device(rc); 895b285192aSMauro Carvalho Chehab dev->remote = NULL; 896b285192aSMauro Carvalho Chehab kfree(ir); 897b285192aSMauro Carvalho Chehab return err; 898b285192aSMauro Carvalho Chehab } 899b285192aSMauro Carvalho Chehab 900b285192aSMauro Carvalho Chehab void saa7134_input_fini(struct saa7134_dev *dev) 901b285192aSMauro Carvalho Chehab { 902b285192aSMauro Carvalho Chehab if (NULL == dev->remote) 903b285192aSMauro Carvalho Chehab return; 904b285192aSMauro Carvalho Chehab 905b285192aSMauro Carvalho Chehab saa7134_ir_stop(dev); 906b285192aSMauro Carvalho Chehab rc_unregister_device(dev->remote->dev); 907b285192aSMauro Carvalho Chehab kfree(dev->remote); 908b285192aSMauro Carvalho Chehab dev->remote = NULL; 909b285192aSMauro Carvalho Chehab } 910b285192aSMauro Carvalho Chehab 911b285192aSMauro Carvalho Chehab void saa7134_probe_i2c_ir(struct saa7134_dev *dev) 912b285192aSMauro Carvalho Chehab { 913b285192aSMauro Carvalho Chehab struct i2c_board_info info; 914b285192aSMauro Carvalho Chehab struct i2c_msg msg_msi = { 915b285192aSMauro Carvalho Chehab .addr = 0x50, 916b285192aSMauro Carvalho Chehab .flags = I2C_M_RD, 917b285192aSMauro Carvalho Chehab .len = 0, 918b285192aSMauro Carvalho Chehab .buf = NULL, 919b285192aSMauro Carvalho Chehab }; 920b285192aSMauro Carvalho Chehab int rc; 921b285192aSMauro Carvalho Chehab 922b285192aSMauro Carvalho Chehab if (disable_ir) { 923b285192aSMauro Carvalho Chehab dprintk("IR has been disabled, not probing for i2c remote\n"); 924b285192aSMauro Carvalho Chehab return; 925b285192aSMauro Carvalho Chehab } 926b285192aSMauro Carvalho Chehab 927b285192aSMauro Carvalho Chehab memset(&info, 0, sizeof(struct i2c_board_info)); 928b285192aSMauro Carvalho Chehab memset(&dev->init_data, 0, sizeof(dev->init_data)); 929b285192aSMauro Carvalho Chehab strlcpy(info.type, "ir_video", I2C_NAME_SIZE); 930b285192aSMauro Carvalho Chehab 931b285192aSMauro Carvalho Chehab switch (dev->board) { 932b285192aSMauro Carvalho Chehab case SAA7134_BOARD_PINNACLE_PCTV_110i: 933b285192aSMauro Carvalho Chehab case SAA7134_BOARD_PINNACLE_PCTV_310i: 934b285192aSMauro Carvalho Chehab dev->init_data.name = "Pinnacle PCTV"; 935b285192aSMauro Carvalho Chehab if (pinnacle_remote == 0) { 936b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_pinnacle_color; 937b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_PINNACLE_COLOR; 938b285192aSMauro Carvalho Chehab info.addr = 0x47; 939b285192aSMauro Carvalho Chehab } else { 940b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_pinnacle_grey; 941b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_PINNACLE_GREY; 942b285192aSMauro Carvalho Chehab info.addr = 0x47; 943b285192aSMauro Carvalho Chehab } 944b285192aSMauro Carvalho Chehab break; 945b285192aSMauro Carvalho Chehab case SAA7134_BOARD_UPMOST_PURPLE_TV: 946b285192aSMauro Carvalho Chehab dev->init_data.name = "Purple TV"; 947b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_purpletv; 948b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_PURPLETV; 949b285192aSMauro Carvalho Chehab info.addr = 0x7a; 950b285192aSMauro Carvalho Chehab break; 951b285192aSMauro Carvalho Chehab case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS: 952b285192aSMauro Carvalho Chehab dev->init_data.name = "MSI TV@nywhere Plus"; 953b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_msi_tvanywhere_plus; 954b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_MSI_TVANYWHERE_PLUS; 955b285192aSMauro Carvalho Chehab /* 956b285192aSMauro Carvalho Chehab * MSI TV@nyware Plus requires more frequent polling 957b285192aSMauro Carvalho Chehab * otherwise it will miss some keypresses 958b285192aSMauro Carvalho Chehab */ 959b285192aSMauro Carvalho Chehab dev->init_data.polling_interval = 50; 960b285192aSMauro Carvalho Chehab info.addr = 0x30; 961b285192aSMauro Carvalho Chehab /* MSI TV@nywhere Plus controller doesn't seem to 962b285192aSMauro Carvalho Chehab respond to probes unless we read something from 963b285192aSMauro Carvalho Chehab an existing device. Weird... 964b285192aSMauro Carvalho Chehab REVISIT: might no longer be needed */ 965b285192aSMauro Carvalho Chehab rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1); 966b285192aSMauro Carvalho Chehab dprintk("probe 0x%02x @ %s: %s\n", 967b285192aSMauro Carvalho Chehab msg_msi.addr, dev->i2c_adap.name, 968b285192aSMauro Carvalho Chehab (1 == rc) ? "yes" : "no"); 969b285192aSMauro Carvalho Chehab break; 970b285192aSMauro Carvalho Chehab case SAA7134_BOARD_KWORLD_PC150U: 971b285192aSMauro Carvalho Chehab /* copied and modified from MSI TV@nywhere Plus */ 972b285192aSMauro Carvalho Chehab dev->init_data.name = "Kworld PC150-U"; 973b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_kworld_pc150u; 974b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_KWORLD_PC150U; 975b285192aSMauro Carvalho Chehab info.addr = 0x30; 976b285192aSMauro Carvalho Chehab /* MSI TV@nywhere Plus controller doesn't seem to 977b285192aSMauro Carvalho Chehab respond to probes unless we read something from 978b285192aSMauro Carvalho Chehab an existing device. Weird... 979b285192aSMauro Carvalho Chehab REVISIT: might no longer be needed */ 980b285192aSMauro Carvalho Chehab rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1); 981b285192aSMauro Carvalho Chehab dprintk("probe 0x%02x @ %s: %s\n", 982b285192aSMauro Carvalho Chehab msg_msi.addr, dev->i2c_adap.name, 983b285192aSMauro Carvalho Chehab (1 == rc) ? "yes" : "no"); 984b285192aSMauro Carvalho Chehab break; 985b285192aSMauro Carvalho Chehab case SAA7134_BOARD_HAUPPAUGE_HVR1110: 986b285192aSMauro Carvalho Chehab dev->init_data.name = "HVR 1110"; 987b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_hvr1110; 988b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_HAUPPAUGE; 989b285192aSMauro Carvalho Chehab info.addr = 0x71; 990b285192aSMauro Carvalho Chehab break; 991b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_607FM_MK3: 992b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_607FM_MK5: 993b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_609FM_MK3: 994b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_609FM_MK5: 995b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_607RDS_MK3: 996b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_607RDS_MK5: 997b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_609RDS_MK3: 998b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_609RDS_MK5: 999b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_M6: 1000b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_M63: 1001b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_M6_EXTRA: 1002b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_H6: 1003b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_X7: 1004b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_H7: 1005b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_A7: 1006b285192aSMauro Carvalho Chehab dev->init_data.name = "BeholdTV"; 1007b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_beholdm6xx; 1008b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_BEHOLD; 1009c003ab1bSDavid Härdeman dev->init_data.type = RC_BIT_NEC; 1010b285192aSMauro Carvalho Chehab info.addr = 0x2d; 1011b285192aSMauro Carvalho Chehab break; 1012b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_CARDBUS_501: 1013b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: 1014b285192aSMauro Carvalho Chehab info.addr = 0x40; 1015b285192aSMauro Carvalho Chehab break; 101634fe2784SOndrej Zary case SAA7134_BOARD_AVERMEDIA_A706: 101734fe2784SOndrej Zary info.addr = 0x41; 101834fe2784SOndrej Zary break; 1019b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYDVB_TRIO: 1020b285192aSMauro Carvalho Chehab dev->init_data.name = "FlyDVB Trio"; 1021b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_flydvb_trio; 1022b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_FLYDVB; 1023b285192aSMauro Carvalho Chehab info.addr = 0x0b; 1024b285192aSMauro Carvalho Chehab break; 1025b285192aSMauro Carvalho Chehab default: 1026b285192aSMauro Carvalho Chehab dprintk("No I2C IR support for board %x\n", dev->board); 1027b285192aSMauro Carvalho Chehab return; 1028b285192aSMauro Carvalho Chehab } 1029b285192aSMauro Carvalho Chehab 1030b285192aSMauro Carvalho Chehab if (dev->init_data.name) 1031b285192aSMauro Carvalho Chehab info.platform_data = &dev->init_data; 1032b285192aSMauro Carvalho Chehab i2c_new_device(&dev->i2c_adap, &info); 1033b285192aSMauro Carvalho Chehab } 1034b285192aSMauro Carvalho Chehab 1035b285192aSMauro Carvalho Chehab static int saa7134_raw_decode_irq(struct saa7134_dev *dev) 1036b285192aSMauro Carvalho Chehab { 1037b285192aSMauro Carvalho Chehab struct saa7134_card_ir *ir = dev->remote; 1038b285192aSMauro Carvalho Chehab unsigned long timeout; 1039b285192aSMauro Carvalho Chehab int space; 1040b285192aSMauro Carvalho Chehab 1041b285192aSMauro Carvalho Chehab /* Generate initial event */ 1042b285192aSMauro Carvalho Chehab saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 1043b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 1044b285192aSMauro Carvalho Chehab space = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown; 1045b285192aSMauro Carvalho Chehab ir_raw_event_store_edge(dev->remote->dev, space ? IR_SPACE : IR_PULSE); 1046b285192aSMauro Carvalho Chehab 1047b285192aSMauro Carvalho Chehab /* 1048b285192aSMauro Carvalho Chehab * Wait 15 ms from the start of the first IR event before processing 1049b285192aSMauro Carvalho Chehab * the event. This time is enough for NEC protocol. May need adjustments 1050b285192aSMauro Carvalho Chehab * to work with other protocols. 1051b285192aSMauro Carvalho Chehab */ 1052b285192aSMauro Carvalho Chehab smp_mb(); 1053b285192aSMauro Carvalho Chehab 1054b285192aSMauro Carvalho Chehab if (!timer_pending(&ir->timer)) { 1055b285192aSMauro Carvalho Chehab timeout = jiffies + msecs_to_jiffies(15); 1056b285192aSMauro Carvalho Chehab mod_timer(&ir->timer, timeout); 1057b285192aSMauro Carvalho Chehab } 1058b285192aSMauro Carvalho Chehab 1059b285192aSMauro Carvalho Chehab return 1; 1060b285192aSMauro Carvalho Chehab } 1061