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 86b285192aSMauro Carvalho Chehab rc_keydown_notimeout(ir->dev, 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)))) { 93b285192aSMauro Carvalho Chehab rc_keydown_notimeout(ir->dev, 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)))) { 101b285192aSMauro Carvalho Chehab rc_keydown_notimeout(ir->dev, 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 111b285192aSMauro Carvalho Chehab static int get_key_flydvb_trio(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) 112b285192aSMauro Carvalho Chehab { 113b285192aSMauro Carvalho Chehab int gpio; 114b285192aSMauro Carvalho Chehab int attempt = 0; 115b285192aSMauro Carvalho Chehab unsigned char b; 116b285192aSMauro Carvalho Chehab 117b285192aSMauro Carvalho Chehab /* We need this to access GPI Used by the saa_readl macro. */ 118b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = ir->c->adapter->algo_data; 119b285192aSMauro Carvalho Chehab 120b285192aSMauro Carvalho Chehab if (dev == NULL) { 121b285192aSMauro Carvalho Chehab i2cdprintk("get_key_flydvb_trio: " 122b285192aSMauro Carvalho Chehab "ir->c->adapter->algo_data is NULL!\n"); 123b285192aSMauro Carvalho Chehab return -EIO; 124b285192aSMauro Carvalho Chehab } 125b285192aSMauro Carvalho Chehab 126b285192aSMauro Carvalho Chehab /* rising SAA7134_GPIGPRESCAN reads the status */ 127b285192aSMauro Carvalho Chehab saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 128b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 129b285192aSMauro Carvalho Chehab 130b285192aSMauro Carvalho Chehab gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2); 131b285192aSMauro Carvalho Chehab 132b285192aSMauro Carvalho Chehab if (0x40000 & ~gpio) 133b285192aSMauro Carvalho Chehab return 0; /* No button press */ 134b285192aSMauro Carvalho Chehab 135b285192aSMauro Carvalho Chehab /* No button press - only before first key pressed */ 136b285192aSMauro Carvalho Chehab if (b == 0xFF) 137b285192aSMauro Carvalho Chehab return 0; 138b285192aSMauro Carvalho Chehab 139b285192aSMauro Carvalho Chehab /* poll IR chip */ 140b285192aSMauro Carvalho Chehab /* weak up the IR chip */ 141b285192aSMauro Carvalho Chehab b = 0; 142b285192aSMauro Carvalho Chehab 143b285192aSMauro Carvalho Chehab while (1 != i2c_master_send(ir->c, &b, 1)) { 144b285192aSMauro Carvalho Chehab if ((attempt++) < 10) { 145b285192aSMauro Carvalho Chehab /* 146b285192aSMauro Carvalho Chehab * wait a bit for next attempt - 147b285192aSMauro Carvalho Chehab * I don't know how make it better 148b285192aSMauro Carvalho Chehab */ 149b285192aSMauro Carvalho Chehab msleep(10); 150b285192aSMauro Carvalho Chehab continue; 151b285192aSMauro Carvalho Chehab } 152b285192aSMauro Carvalho Chehab i2cdprintk("send wake up byte to pic16C505 (IR chip)" 153b285192aSMauro Carvalho Chehab "failed %dx\n", attempt); 154b285192aSMauro Carvalho Chehab return -EIO; 155b285192aSMauro Carvalho Chehab } 156b285192aSMauro Carvalho Chehab if (1 != i2c_master_recv(ir->c, &b, 1)) { 157b285192aSMauro Carvalho Chehab i2cdprintk("read error\n"); 158b285192aSMauro Carvalho Chehab return -EIO; 159b285192aSMauro Carvalho Chehab } 160b285192aSMauro Carvalho Chehab 161b285192aSMauro Carvalho Chehab *ir_key = b; 162b285192aSMauro Carvalho Chehab *ir_raw = b; 163b285192aSMauro Carvalho Chehab return 1; 164b285192aSMauro Carvalho Chehab } 165b285192aSMauro Carvalho Chehab 166b285192aSMauro Carvalho Chehab static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, u32 *ir_key, 167b285192aSMauro Carvalho Chehab u32 *ir_raw) 168b285192aSMauro Carvalho Chehab { 169b285192aSMauro Carvalho Chehab unsigned char b; 170b285192aSMauro Carvalho Chehab int gpio; 171b285192aSMauro Carvalho Chehab 172b285192aSMauro Carvalho Chehab /* <dev> is needed to access GPIO. Used by the saa_readl macro. */ 173b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = ir->c->adapter->algo_data; 174b285192aSMauro Carvalho Chehab if (dev == NULL) { 175b285192aSMauro Carvalho Chehab i2cdprintk("get_key_msi_tvanywhere_plus: " 176b285192aSMauro Carvalho Chehab "ir->c->adapter->algo_data is NULL!\n"); 177b285192aSMauro Carvalho Chehab return -EIO; 178b285192aSMauro Carvalho Chehab } 179b285192aSMauro Carvalho Chehab 180b285192aSMauro Carvalho Chehab /* rising SAA7134_GPIO_GPRESCAN reads the status */ 181b285192aSMauro Carvalho Chehab 182b285192aSMauro Carvalho Chehab saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 183b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 184b285192aSMauro Carvalho Chehab 185b285192aSMauro Carvalho Chehab gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2); 186b285192aSMauro Carvalho Chehab 187b285192aSMauro Carvalho Chehab /* GPIO&0x40 is pulsed low when a button is pressed. Don't do 188b285192aSMauro Carvalho Chehab I2C receive if gpio&0x40 is not low. */ 189b285192aSMauro Carvalho Chehab 190b285192aSMauro Carvalho Chehab if (gpio & 0x40) 191b285192aSMauro Carvalho Chehab return 0; /* No button press */ 192b285192aSMauro Carvalho Chehab 193b285192aSMauro Carvalho Chehab /* GPIO says there is a button press. Get it. */ 194b285192aSMauro Carvalho Chehab 195b285192aSMauro Carvalho Chehab if (1 != i2c_master_recv(ir->c, &b, 1)) { 196b285192aSMauro Carvalho Chehab i2cdprintk("read error\n"); 197b285192aSMauro Carvalho Chehab return -EIO; 198b285192aSMauro Carvalho Chehab } 199b285192aSMauro Carvalho Chehab 200b285192aSMauro Carvalho Chehab /* No button press */ 201b285192aSMauro Carvalho Chehab 202b285192aSMauro Carvalho Chehab if (b == 0xff) 203b285192aSMauro Carvalho Chehab return 0; 204b285192aSMauro Carvalho Chehab 205b285192aSMauro Carvalho Chehab /* Button pressed */ 206b285192aSMauro Carvalho Chehab 207b285192aSMauro Carvalho Chehab dprintk("get_key_msi_tvanywhere_plus: Key = 0x%02X\n", b); 208b285192aSMauro Carvalho Chehab *ir_key = b; 209b285192aSMauro Carvalho Chehab *ir_raw = b; 210b285192aSMauro Carvalho Chehab return 1; 211b285192aSMauro Carvalho Chehab } 212b285192aSMauro Carvalho Chehab 213b285192aSMauro Carvalho Chehab /* copied and modified from get_key_msi_tvanywhere_plus() */ 214b285192aSMauro Carvalho Chehab static int get_key_kworld_pc150u(struct IR_i2c *ir, u32 *ir_key, 215b285192aSMauro Carvalho Chehab u32 *ir_raw) 216b285192aSMauro Carvalho Chehab { 217b285192aSMauro Carvalho Chehab unsigned char b; 218b285192aSMauro Carvalho Chehab unsigned int gpio; 219b285192aSMauro Carvalho Chehab 220b285192aSMauro Carvalho Chehab /* <dev> is needed to access GPIO. Used by the saa_readl macro. */ 221b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = ir->c->adapter->algo_data; 222b285192aSMauro Carvalho Chehab if (dev == NULL) { 223b285192aSMauro Carvalho Chehab i2cdprintk("get_key_kworld_pc150u: " 224b285192aSMauro Carvalho Chehab "ir->c->adapter->algo_data is NULL!\n"); 225b285192aSMauro Carvalho Chehab return -EIO; 226b285192aSMauro Carvalho Chehab } 227b285192aSMauro Carvalho Chehab 228b285192aSMauro Carvalho Chehab /* rising SAA7134_GPIO_GPRESCAN reads the status */ 229b285192aSMauro Carvalho Chehab 230b285192aSMauro Carvalho Chehab saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 231b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 232b285192aSMauro Carvalho Chehab 233b285192aSMauro Carvalho Chehab gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2); 234b285192aSMauro Carvalho Chehab 235b285192aSMauro Carvalho Chehab /* GPIO&0x100 is pulsed low when a button is pressed. Don't do 236b285192aSMauro Carvalho Chehab I2C receive if gpio&0x100 is not low. */ 237b285192aSMauro Carvalho Chehab 238b285192aSMauro Carvalho Chehab if (gpio & 0x100) 239b285192aSMauro Carvalho Chehab return 0; /* No button press */ 240b285192aSMauro Carvalho Chehab 241b285192aSMauro Carvalho Chehab /* GPIO says there is a button press. Get it. */ 242b285192aSMauro Carvalho Chehab 243b285192aSMauro Carvalho Chehab if (1 != i2c_master_recv(ir->c, &b, 1)) { 244b285192aSMauro Carvalho Chehab i2cdprintk("read error\n"); 245b285192aSMauro Carvalho Chehab return -EIO; 246b285192aSMauro Carvalho Chehab } 247b285192aSMauro Carvalho Chehab 248b285192aSMauro Carvalho Chehab /* No button press */ 249b285192aSMauro Carvalho Chehab 250b285192aSMauro Carvalho Chehab if (b == 0xff) 251b285192aSMauro Carvalho Chehab return 0; 252b285192aSMauro Carvalho Chehab 253b285192aSMauro Carvalho Chehab /* Button pressed */ 254b285192aSMauro Carvalho Chehab 255b285192aSMauro Carvalho Chehab dprintk("get_key_kworld_pc150u: Key = 0x%02X\n", b); 256b285192aSMauro Carvalho Chehab *ir_key = b; 257b285192aSMauro Carvalho Chehab *ir_raw = b; 258b285192aSMauro Carvalho Chehab return 1; 259b285192aSMauro Carvalho Chehab } 260b285192aSMauro Carvalho Chehab 261b285192aSMauro Carvalho Chehab static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) 262b285192aSMauro Carvalho Chehab { 263b285192aSMauro Carvalho Chehab unsigned char b; 264b285192aSMauro Carvalho Chehab 265b285192aSMauro Carvalho Chehab /* poll IR chip */ 266b285192aSMauro Carvalho Chehab if (1 != i2c_master_recv(ir->c, &b, 1)) { 267b285192aSMauro Carvalho Chehab i2cdprintk("read error\n"); 268b285192aSMauro Carvalho Chehab return -EIO; 269b285192aSMauro Carvalho Chehab } 270b285192aSMauro Carvalho Chehab 271b285192aSMauro Carvalho Chehab /* no button press */ 272b285192aSMauro Carvalho Chehab if (b==0) 273b285192aSMauro Carvalho Chehab return 0; 274b285192aSMauro Carvalho Chehab 275b285192aSMauro Carvalho Chehab /* repeating */ 276b285192aSMauro Carvalho Chehab if (b & 0x80) 277b285192aSMauro Carvalho Chehab return 1; 278b285192aSMauro Carvalho Chehab 279b285192aSMauro Carvalho Chehab *ir_key = b; 280b285192aSMauro Carvalho Chehab *ir_raw = b; 281b285192aSMauro Carvalho Chehab return 1; 282b285192aSMauro Carvalho Chehab } 283b285192aSMauro Carvalho Chehab 284b285192aSMauro Carvalho Chehab static int get_key_hvr1110(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) 285b285192aSMauro Carvalho Chehab { 286b285192aSMauro Carvalho Chehab unsigned char buf[5]; 287b285192aSMauro Carvalho Chehab 288b285192aSMauro Carvalho Chehab /* poll IR chip */ 289b285192aSMauro Carvalho Chehab if (5 != i2c_master_recv(ir->c, buf, 5)) 290b285192aSMauro Carvalho Chehab return -EIO; 291b285192aSMauro Carvalho Chehab 292b285192aSMauro Carvalho Chehab /* Check if some key were pressed */ 293b285192aSMauro Carvalho Chehab if (!(buf[0] & 0x80)) 294b285192aSMauro Carvalho Chehab return 0; 295b285192aSMauro Carvalho Chehab 296b285192aSMauro Carvalho Chehab /* 297b285192aSMauro Carvalho Chehab * buf[3] & 0x80 is always high. 298b285192aSMauro Carvalho Chehab * buf[3] & 0x40 is a parity bit. A repeat event is marked 299b285192aSMauro Carvalho Chehab * by preserving it into two separate readings 300b285192aSMauro Carvalho Chehab * buf[4] bits 0 and 1, and buf[1] and buf[2] are always 301b285192aSMauro Carvalho Chehab * zero. 302b285192aSMauro Carvalho Chehab */ 303b285192aSMauro Carvalho Chehab *ir_key = 0x1fff & ((buf[3] << 8) | (buf[4] >> 2)); 304b285192aSMauro Carvalho Chehab *ir_raw = *ir_key; 305b285192aSMauro Carvalho Chehab return 1; 306b285192aSMauro Carvalho Chehab } 307b285192aSMauro Carvalho Chehab 308b285192aSMauro Carvalho Chehab 309b285192aSMauro Carvalho Chehab static int get_key_beholdm6xx(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) 310b285192aSMauro Carvalho Chehab { 311b285192aSMauro Carvalho Chehab unsigned char data[12]; 312b285192aSMauro Carvalho Chehab u32 gpio; 313b285192aSMauro Carvalho Chehab 314b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = ir->c->adapter->algo_data; 315b285192aSMauro Carvalho Chehab 316b285192aSMauro Carvalho Chehab /* rising SAA7134_GPIO_GPRESCAN reads the status */ 317b285192aSMauro Carvalho Chehab saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 318b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 319b285192aSMauro Carvalho Chehab 320b285192aSMauro Carvalho Chehab gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2); 321b285192aSMauro Carvalho Chehab 322b285192aSMauro Carvalho Chehab if (0x400000 & ~gpio) 323b285192aSMauro Carvalho Chehab return 0; /* No button press */ 324b285192aSMauro Carvalho Chehab 325b285192aSMauro Carvalho Chehab ir->c->addr = 0x5a >> 1; 326b285192aSMauro Carvalho Chehab 327b285192aSMauro Carvalho Chehab if (12 != i2c_master_recv(ir->c, data, 12)) { 328b285192aSMauro Carvalho Chehab i2cdprintk("read error\n"); 329b285192aSMauro Carvalho Chehab return -EIO; 330b285192aSMauro Carvalho Chehab } 331b285192aSMauro Carvalho Chehab 332b285192aSMauro Carvalho Chehab if (data[9] != (unsigned char)(~data[8])) 333b285192aSMauro Carvalho Chehab return 0; 334b285192aSMauro Carvalho Chehab 335b285192aSMauro Carvalho Chehab *ir_raw = ((data[10] << 16) | (data[11] << 8) | (data[9] << 0)); 336b285192aSMauro Carvalho Chehab *ir_key = *ir_raw; 337b285192aSMauro Carvalho Chehab 338b285192aSMauro Carvalho Chehab return 1; 339b285192aSMauro Carvalho Chehab } 340b285192aSMauro Carvalho Chehab 341b285192aSMauro Carvalho Chehab /* Common (grey or coloured) pinnacle PCTV remote handling 342b285192aSMauro Carvalho Chehab * 343b285192aSMauro Carvalho Chehab */ 344b285192aSMauro Carvalho Chehab static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw, 345b285192aSMauro Carvalho Chehab int parity_offset, int marker, int code_modulo) 346b285192aSMauro Carvalho Chehab { 347b285192aSMauro Carvalho Chehab unsigned char b[4]; 348b285192aSMauro Carvalho Chehab unsigned int start = 0,parity = 0,code = 0; 349b285192aSMauro Carvalho Chehab 350b285192aSMauro Carvalho Chehab /* poll IR chip */ 351b285192aSMauro Carvalho Chehab if (4 != i2c_master_recv(ir->c, b, 4)) { 352b285192aSMauro Carvalho Chehab i2cdprintk("read error\n"); 353b285192aSMauro Carvalho Chehab return -EIO; 354b285192aSMauro Carvalho Chehab } 355b285192aSMauro Carvalho Chehab 356b285192aSMauro Carvalho Chehab for (start = 0; start < ARRAY_SIZE(b); start++) { 357b285192aSMauro Carvalho Chehab if (b[start] == marker) { 358b285192aSMauro Carvalho Chehab code=b[(start+parity_offset + 1) % 4]; 359b285192aSMauro Carvalho Chehab parity=b[(start+parity_offset) % 4]; 360b285192aSMauro Carvalho Chehab } 361b285192aSMauro Carvalho Chehab } 362b285192aSMauro Carvalho Chehab 363b285192aSMauro Carvalho Chehab /* Empty Request */ 364b285192aSMauro Carvalho Chehab if (parity == 0) 365b285192aSMauro Carvalho Chehab return 0; 366b285192aSMauro Carvalho Chehab 367b285192aSMauro Carvalho Chehab /* Repeating... */ 368b285192aSMauro Carvalho Chehab if (ir->old == parity) 369b285192aSMauro Carvalho Chehab return 0; 370b285192aSMauro Carvalho Chehab 371b285192aSMauro Carvalho Chehab ir->old = parity; 372b285192aSMauro Carvalho Chehab 373b285192aSMauro Carvalho Chehab /* drop special codes when a key is held down a long time for the grey controller 374b285192aSMauro Carvalho Chehab In this case, the second bit of the code is asserted */ 375b285192aSMauro Carvalho Chehab if (marker == 0xfe && (code & 0x40)) 376b285192aSMauro Carvalho Chehab return 0; 377b285192aSMauro Carvalho Chehab 378b285192aSMauro Carvalho Chehab code %= code_modulo; 379b285192aSMauro Carvalho Chehab 380b285192aSMauro Carvalho Chehab *ir_raw = code; 381b285192aSMauro Carvalho Chehab *ir_key = code; 382b285192aSMauro Carvalho Chehab 383b285192aSMauro Carvalho Chehab i2cdprintk("Pinnacle PCTV key %02x\n", code); 384b285192aSMauro Carvalho Chehab 385b285192aSMauro Carvalho Chehab return 1; 386b285192aSMauro Carvalho Chehab } 387b285192aSMauro Carvalho Chehab 388b285192aSMauro Carvalho Chehab /* The grey pinnacle PCTV remote 389b285192aSMauro Carvalho Chehab * 390b285192aSMauro Carvalho Chehab * There are one issue with this remote: 391b285192aSMauro Carvalho Chehab * - I2c packet does not change when the same key is pressed quickly. The workaround 392b285192aSMauro Carvalho Chehab * is to hold down each key for about half a second, so that another code is generated 393b285192aSMauro Carvalho Chehab * in the i2c packet, and the function can distinguish key presses. 394b285192aSMauro Carvalho Chehab * 395b285192aSMauro Carvalho Chehab * Sylvain Pasche <sylvain.pasche@gmail.com> 396b285192aSMauro Carvalho Chehab */ 397b285192aSMauro Carvalho Chehab static int get_key_pinnacle_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) 398b285192aSMauro Carvalho Chehab { 399b285192aSMauro Carvalho Chehab 400b285192aSMauro Carvalho Chehab return get_key_pinnacle(ir, ir_key, ir_raw, 1, 0xfe, 0xff); 401b285192aSMauro Carvalho Chehab } 402b285192aSMauro Carvalho Chehab 403b285192aSMauro Carvalho Chehab 404b285192aSMauro Carvalho Chehab /* The new pinnacle PCTV remote (with the colored buttons) 405b285192aSMauro Carvalho Chehab * 406b285192aSMauro Carvalho Chehab * Ricardo Cerqueira <v4l@cerqueira.org> 407b285192aSMauro Carvalho Chehab */ 408b285192aSMauro Carvalho Chehab static int get_key_pinnacle_color(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) 409b285192aSMauro Carvalho Chehab { 410b285192aSMauro Carvalho Chehab /* code_modulo parameter (0x88) is used to reduce code value to fit inside IR_KEYTAB_SIZE 411b285192aSMauro Carvalho Chehab * 412b285192aSMauro Carvalho Chehab * this is the only value that results in 42 unique 413b285192aSMauro Carvalho Chehab * codes < 128 414b285192aSMauro Carvalho Chehab */ 415b285192aSMauro Carvalho Chehab 416b285192aSMauro Carvalho Chehab return get_key_pinnacle(ir, ir_key, ir_raw, 2, 0x80, 0x88); 417b285192aSMauro Carvalho Chehab } 418b285192aSMauro Carvalho Chehab 419b285192aSMauro Carvalho Chehab void saa7134_input_irq(struct saa7134_dev *dev) 420b285192aSMauro Carvalho Chehab { 421b285192aSMauro Carvalho Chehab struct saa7134_card_ir *ir; 422b285192aSMauro Carvalho Chehab 423b285192aSMauro Carvalho Chehab if (!dev || !dev->remote) 424b285192aSMauro Carvalho Chehab return; 425b285192aSMauro Carvalho Chehab 426b285192aSMauro Carvalho Chehab ir = dev->remote; 427b285192aSMauro Carvalho Chehab if (!ir->running) 428b285192aSMauro Carvalho Chehab return; 429b285192aSMauro Carvalho Chehab 430b285192aSMauro Carvalho Chehab if (!ir->polling && !ir->raw_decode) { 431b285192aSMauro Carvalho Chehab build_key(dev); 432b285192aSMauro Carvalho Chehab } else if (ir->raw_decode) { 433b285192aSMauro Carvalho Chehab saa7134_raw_decode_irq(dev); 434b285192aSMauro Carvalho Chehab } 435b285192aSMauro Carvalho Chehab } 436b285192aSMauro Carvalho Chehab 437b285192aSMauro Carvalho Chehab static void saa7134_input_timer(unsigned long data) 438b285192aSMauro Carvalho Chehab { 439b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = (struct saa7134_dev *)data; 440b285192aSMauro Carvalho Chehab struct saa7134_card_ir *ir = dev->remote; 441b285192aSMauro Carvalho Chehab 442b285192aSMauro Carvalho Chehab build_key(dev); 443b285192aSMauro Carvalho Chehab mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); 444b285192aSMauro Carvalho Chehab } 445b285192aSMauro Carvalho Chehab 446b285192aSMauro Carvalho Chehab static void ir_raw_decode_timer_end(unsigned long data) 447b285192aSMauro Carvalho Chehab { 448b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = (struct saa7134_dev *)data; 449b285192aSMauro Carvalho Chehab 450b285192aSMauro Carvalho Chehab ir_raw_event_handle(dev->remote->dev); 451b285192aSMauro Carvalho Chehab } 452b285192aSMauro Carvalho Chehab 453b285192aSMauro Carvalho Chehab static int __saa7134_ir_start(void *priv) 454b285192aSMauro Carvalho Chehab { 455b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = priv; 456b285192aSMauro Carvalho Chehab struct saa7134_card_ir *ir; 457b285192aSMauro Carvalho Chehab 458b285192aSMauro Carvalho Chehab if (!dev || !dev->remote) 459b285192aSMauro Carvalho Chehab return -EINVAL; 460b285192aSMauro Carvalho Chehab 461b285192aSMauro Carvalho Chehab ir = dev->remote; 462b285192aSMauro Carvalho Chehab if (ir->running) 463b285192aSMauro Carvalho Chehab return 0; 464b285192aSMauro Carvalho Chehab 465b285192aSMauro Carvalho Chehab /* Moved here from saa7134_input_init1() because the latter 466b285192aSMauro Carvalho Chehab * is not called on device resume */ 467b285192aSMauro Carvalho Chehab switch (dev->board) { 468b285192aSMauro Carvalho Chehab case SAA7134_BOARD_MD2819: 469b285192aSMauro Carvalho Chehab case SAA7134_BOARD_KWORLD_VSTREAM_XPERT: 470b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_305: 471b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_307: 472b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_305: 473b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_505: 474b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_307: 475b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_507: 476b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_507UA: 477b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_GO_007_FM: 478b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_M102: 479b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS: 480b285192aSMauro Carvalho Chehab /* Without this we won't receive key up events */ 481b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE0, 0x4); 482b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); 483b285192aSMauro Carvalho Chehab break; 484b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_777: 485b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_A16AR: 486b285192aSMauro Carvalho Chehab /* Without this we won't receive key up events */ 487b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE1, 0x1); 488b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1); 489b285192aSMauro Carvalho Chehab break; 490b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_A16D: 491b285192aSMauro Carvalho Chehab /* Without this we won't receive key up events */ 492b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE1, 0x1); 493b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1); 494b285192aSMauro Carvalho Chehab break; 495b285192aSMauro Carvalho Chehab case SAA7134_BOARD_GOTVIEW_7135: 496b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE1, 0x80); 497b285192aSMauro Carvalho Chehab break; 498b285192aSMauro Carvalho Chehab } 499b285192aSMauro Carvalho Chehab 500b285192aSMauro Carvalho Chehab ir->running = true; 501b285192aSMauro Carvalho Chehab 502b285192aSMauro Carvalho Chehab if (ir->polling) { 503b285192aSMauro Carvalho Chehab setup_timer(&ir->timer, saa7134_input_timer, 504b285192aSMauro Carvalho Chehab (unsigned long)dev); 505b285192aSMauro Carvalho Chehab ir->timer.expires = jiffies + HZ; 506b285192aSMauro Carvalho Chehab add_timer(&ir->timer); 507b285192aSMauro Carvalho Chehab } else if (ir->raw_decode) { 508b285192aSMauro Carvalho Chehab /* set timer_end for code completion */ 509b285192aSMauro Carvalho Chehab setup_timer(&ir->timer, ir_raw_decode_timer_end, 510b285192aSMauro Carvalho Chehab (unsigned long)dev); 511b285192aSMauro Carvalho Chehab } 512b285192aSMauro Carvalho Chehab 513b285192aSMauro Carvalho Chehab return 0; 514b285192aSMauro Carvalho Chehab } 515b285192aSMauro Carvalho Chehab 516b285192aSMauro Carvalho Chehab static void __saa7134_ir_stop(void *priv) 517b285192aSMauro Carvalho Chehab { 518b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = priv; 519b285192aSMauro Carvalho Chehab struct saa7134_card_ir *ir; 520b285192aSMauro Carvalho Chehab 521b285192aSMauro Carvalho Chehab if (!dev || !dev->remote) 522b285192aSMauro Carvalho Chehab return; 523b285192aSMauro Carvalho Chehab 524b285192aSMauro Carvalho Chehab ir = dev->remote; 525b285192aSMauro Carvalho Chehab if (!ir->running) 526b285192aSMauro Carvalho Chehab return; 527b285192aSMauro Carvalho Chehab 528b285192aSMauro Carvalho Chehab if (ir->polling || ir->raw_decode) 529b285192aSMauro Carvalho Chehab del_timer_sync(&ir->timer); 530b285192aSMauro Carvalho Chehab 531b285192aSMauro Carvalho Chehab ir->running = false; 532b285192aSMauro Carvalho Chehab 533b285192aSMauro Carvalho Chehab return; 534b285192aSMauro Carvalho Chehab } 535b285192aSMauro Carvalho Chehab 536b285192aSMauro Carvalho Chehab int saa7134_ir_start(struct saa7134_dev *dev) 537b285192aSMauro Carvalho Chehab { 538b285192aSMauro Carvalho Chehab if (dev->remote->users) 539b285192aSMauro Carvalho Chehab return __saa7134_ir_start(dev); 540b285192aSMauro Carvalho Chehab 541b285192aSMauro Carvalho Chehab return 0; 542b285192aSMauro Carvalho Chehab } 543b285192aSMauro Carvalho Chehab 544b285192aSMauro Carvalho Chehab void saa7134_ir_stop(struct saa7134_dev *dev) 545b285192aSMauro Carvalho Chehab { 546b285192aSMauro Carvalho Chehab if (dev->remote->users) 547b285192aSMauro Carvalho Chehab __saa7134_ir_stop(dev); 548b285192aSMauro Carvalho Chehab } 549b285192aSMauro Carvalho Chehab 550b285192aSMauro Carvalho Chehab static int saa7134_ir_open(struct rc_dev *rc) 551b285192aSMauro Carvalho Chehab { 552b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = rc->priv; 553b285192aSMauro Carvalho Chehab 554b285192aSMauro Carvalho Chehab dev->remote->users++; 555b285192aSMauro Carvalho Chehab return __saa7134_ir_start(dev); 556b285192aSMauro Carvalho Chehab } 557b285192aSMauro Carvalho Chehab 558b285192aSMauro Carvalho Chehab static void saa7134_ir_close(struct rc_dev *rc) 559b285192aSMauro Carvalho Chehab { 560b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = rc->priv; 561b285192aSMauro Carvalho Chehab 562b285192aSMauro Carvalho Chehab dev->remote->users--; 563b285192aSMauro Carvalho Chehab if (!dev->remote->users) 564b285192aSMauro Carvalho Chehab __saa7134_ir_stop(dev); 565b285192aSMauro Carvalho Chehab } 566b285192aSMauro Carvalho Chehab 567b285192aSMauro Carvalho Chehab int saa7134_input_init1(struct saa7134_dev *dev) 568b285192aSMauro Carvalho Chehab { 569b285192aSMauro Carvalho Chehab struct saa7134_card_ir *ir; 570b285192aSMauro Carvalho Chehab struct rc_dev *rc; 571b285192aSMauro Carvalho Chehab char *ir_codes = NULL; 572b285192aSMauro Carvalho Chehab u32 mask_keycode = 0; 573b285192aSMauro Carvalho Chehab u32 mask_keydown = 0; 574b285192aSMauro Carvalho Chehab u32 mask_keyup = 0; 575b285192aSMauro Carvalho Chehab unsigned polling = 0; 576b285192aSMauro Carvalho Chehab bool raw_decode = false; 577b285192aSMauro Carvalho Chehab int err; 578b285192aSMauro Carvalho Chehab 579b285192aSMauro Carvalho Chehab if (dev->has_remote != SAA7134_REMOTE_GPIO) 580b285192aSMauro Carvalho Chehab return -ENODEV; 581b285192aSMauro Carvalho Chehab if (disable_ir) 582b285192aSMauro Carvalho Chehab return -ENODEV; 583b285192aSMauro Carvalho Chehab 584b285192aSMauro Carvalho Chehab /* detect & configure */ 585b285192aSMauro Carvalho Chehab switch (dev->board) { 586b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYVIDEO2000: 587b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYVIDEO3000: 588b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYTVPLATINUM_FM: 589b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYTVPLATINUM_MINI2: 590b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM: 591b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_FLYVIDEO; 592b285192aSMauro Carvalho Chehab mask_keycode = 0xEC00000; 593b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; 594b285192aSMauro Carvalho Chehab break; 595b285192aSMauro Carvalho Chehab case SAA7134_BOARD_CINERGY400: 596b285192aSMauro Carvalho Chehab case SAA7134_BOARD_CINERGY600: 597b285192aSMauro Carvalho Chehab case SAA7134_BOARD_CINERGY600_MK3: 598b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_CINERGY; 599b285192aSMauro Carvalho Chehab mask_keycode = 0x00003f; 600b285192aSMauro Carvalho Chehab mask_keyup = 0x040000; 601b285192aSMauro Carvalho Chehab break; 602b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ECS_TVP3XP: 603b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ECS_TVP3XP_4CB5: 604b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_EZTV; 605b285192aSMauro Carvalho Chehab mask_keycode = 0x00017c; 606b285192aSMauro Carvalho Chehab mask_keyup = 0x000002; 607b285192aSMauro Carvalho Chehab polling = 50; // ms 608b285192aSMauro Carvalho Chehab break; 609b285192aSMauro Carvalho Chehab case SAA7134_BOARD_KWORLD_XPERT: 610b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVACSSMARTTV: 611b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_PIXELVIEW; 612b285192aSMauro Carvalho Chehab mask_keycode = 0x00001F; 613b285192aSMauro Carvalho Chehab mask_keyup = 0x000020; 614b285192aSMauro Carvalho Chehab polling = 50; // ms 615b285192aSMauro Carvalho Chehab break; 616b285192aSMauro Carvalho Chehab case SAA7134_BOARD_MD2819: 617b285192aSMauro Carvalho Chehab case SAA7134_BOARD_KWORLD_VSTREAM_XPERT: 618b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_305: 619b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_307: 620b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_305: 621b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_505: 622b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_307: 623b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_507: 624b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_507UA: 625b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_GO_007_FM: 626b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_M102: 627b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS: 628b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_AVERMEDIA; 629b285192aSMauro Carvalho Chehab mask_keycode = 0x0007C8; 630b285192aSMauro Carvalho Chehab mask_keydown = 0x000010; 631b285192aSMauro Carvalho Chehab polling = 50; // ms 632b285192aSMauro Carvalho Chehab /* GPIO stuff moved to __saa7134_ir_start() */ 633b285192aSMauro Carvalho Chehab break; 634b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_M135A: 635b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_AVERMEDIA_M135A; 636b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ 637b285192aSMauro Carvalho Chehab mask_keyup = 0x0040000; 638b285192aSMauro Carvalho Chehab mask_keycode = 0xffff; 639b285192aSMauro Carvalho Chehab raw_decode = true; 640b285192aSMauro Carvalho Chehab break; 641b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_M733A: 642b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_AVERMEDIA_M733A_RM_K6; 643b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; 644b285192aSMauro Carvalho Chehab mask_keyup = 0x0040000; 645b285192aSMauro Carvalho Chehab mask_keycode = 0xffff; 646b285192aSMauro Carvalho Chehab raw_decode = true; 647b285192aSMauro Carvalho Chehab break; 648b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_777: 649b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_A16AR: 650b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_AVERMEDIA; 651b285192aSMauro Carvalho Chehab mask_keycode = 0x02F200; 652b285192aSMauro Carvalho Chehab mask_keydown = 0x000400; 653b285192aSMauro Carvalho Chehab polling = 50; // ms 654b285192aSMauro Carvalho Chehab /* GPIO stuff moved to __saa7134_ir_start() */ 655b285192aSMauro Carvalho Chehab break; 656b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_A16D: 657b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_AVERMEDIA_A16D; 658b285192aSMauro Carvalho Chehab mask_keycode = 0x02F200; 659b285192aSMauro Carvalho Chehab mask_keydown = 0x000400; 660b285192aSMauro Carvalho Chehab polling = 50; /* ms */ 661b285192aSMauro Carvalho Chehab /* GPIO stuff moved to __saa7134_ir_start() */ 662b285192aSMauro Carvalho Chehab break; 663b285192aSMauro Carvalho Chehab case SAA7134_BOARD_KWORLD_TERMINATOR: 664b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_PIXELVIEW; 665b285192aSMauro Carvalho Chehab mask_keycode = 0x00001f; 666b285192aSMauro Carvalho Chehab mask_keyup = 0x000060; 667b285192aSMauro Carvalho Chehab polling = 50; // ms 668b285192aSMauro Carvalho Chehab break; 669b285192aSMauro Carvalho Chehab case SAA7134_BOARD_MANLI_MTV001: 670b285192aSMauro Carvalho Chehab case SAA7134_BOARD_MANLI_MTV002: 671b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_MANLI; 672b285192aSMauro Carvalho Chehab mask_keycode = 0x001f00; 673b285192aSMauro Carvalho Chehab mask_keyup = 0x004000; 674b285192aSMauro Carvalho Chehab polling = 50; /* ms */ 675b285192aSMauro Carvalho Chehab break; 676b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_409FM: 677b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_401: 678b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_403: 679b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_403FM: 680b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_405: 681b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_405FM: 682b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_407: 683b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_407FM: 684b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_409: 685b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_505FM: 686b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_505RDS_MK5: 687b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_505RDS_MK3: 688b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_507_9FM: 689b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_507RDS_MK3: 690b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_507RDS_MK5: 691b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_MANLI; 692b285192aSMauro Carvalho Chehab mask_keycode = 0x003f00; 693b285192aSMauro Carvalho Chehab mask_keyup = 0x004000; 694b285192aSMauro Carvalho Chehab polling = 50; /* ms */ 695b285192aSMauro Carvalho Chehab break; 696b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: 697b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_BEHOLD_COLUMBUS; 698b285192aSMauro Carvalho Chehab mask_keycode = 0x003f00; 699b285192aSMauro Carvalho Chehab mask_keyup = 0x004000; 700b285192aSMauro Carvalho Chehab polling = 50; // ms 701b285192aSMauro Carvalho Chehab break; 702b285192aSMauro Carvalho Chehab case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS: 703b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_PCTV_SEDNA; 704b285192aSMauro Carvalho Chehab mask_keycode = 0x001f00; 705b285192aSMauro Carvalho Chehab mask_keyup = 0x004000; 706b285192aSMauro Carvalho Chehab polling = 50; // ms 707b285192aSMauro Carvalho Chehab break; 708b285192aSMauro Carvalho Chehab case SAA7134_BOARD_GOTVIEW_7135: 709b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_GOTVIEW7135; 710b285192aSMauro Carvalho Chehab mask_keycode = 0x0003CC; 711b285192aSMauro Carvalho Chehab mask_keydown = 0x000010; 712b285192aSMauro Carvalho Chehab polling = 5; /* ms */ 713b285192aSMauro Carvalho Chehab /* GPIO stuff moved to __saa7134_ir_start() */ 714b285192aSMauro Carvalho Chehab break; 715b285192aSMauro Carvalho Chehab case SAA7134_BOARD_VIDEOMATE_TV_PVR: 716b285192aSMauro Carvalho Chehab case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS: 717b285192aSMauro Carvalho Chehab case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII: 718b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_VIDEOMATE_TV_PVR; 719b285192aSMauro Carvalho Chehab mask_keycode = 0x00003F; 720b285192aSMauro Carvalho Chehab mask_keyup = 0x400000; 721b285192aSMauro Carvalho Chehab polling = 50; // ms 722b285192aSMauro Carvalho Chehab break; 723b285192aSMauro Carvalho Chehab case SAA7134_BOARD_PROTEUS_2309: 724b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_PROTEUS_2309; 725b285192aSMauro Carvalho Chehab mask_keycode = 0x00007F; 726b285192aSMauro Carvalho Chehab mask_keyup = 0x000080; 727b285192aSMauro Carvalho Chehab polling = 50; // ms 728b285192aSMauro Carvalho Chehab break; 729b285192aSMauro Carvalho Chehab case SAA7134_BOARD_VIDEOMATE_DVBT_300: 730b285192aSMauro Carvalho Chehab case SAA7134_BOARD_VIDEOMATE_DVBT_200: 731b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_VIDEOMATE_TV_PVR; 732b285192aSMauro Carvalho Chehab mask_keycode = 0x003F00; 733b285192aSMauro Carvalho Chehab mask_keyup = 0x040000; 734b285192aSMauro Carvalho Chehab break; 735b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYDVBS_LR300: 736b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYDVBT_LR301: 737b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYDVBTDUO: 738b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_FLYDVB; 739b285192aSMauro Carvalho Chehab mask_keycode = 0x0001F00; 740b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; 741b285192aSMauro Carvalho Chehab break; 742b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ASUSTeK_P7131_DUAL: 743b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: 744b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ASUSTeK_P7131_ANALOG: 745b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_ASUS_PC39; 746b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ 747b285192aSMauro Carvalho Chehab mask_keyup = 0x0040000; 748b285192aSMauro Carvalho Chehab mask_keycode = 0xffff; 749b285192aSMauro Carvalho Chehab raw_decode = true; 750b285192aSMauro Carvalho Chehab break; 751b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ASUSTeK_PS3_100: 752b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_ASUS_PS3_100; 753b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; 754b285192aSMauro Carvalho Chehab mask_keyup = 0x0040000; 755b285192aSMauro Carvalho Chehab mask_keycode = 0xffff; 756b285192aSMauro Carvalho Chehab raw_decode = true; 757b285192aSMauro Carvalho Chehab break; 758b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ENCORE_ENLTV: 759b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ENCORE_ENLTV_FM: 760b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_ENCORE_ENLTV; 761b285192aSMauro Carvalho Chehab mask_keycode = 0x00007f; 762b285192aSMauro Carvalho Chehab mask_keyup = 0x040000; 763b285192aSMauro Carvalho Chehab polling = 50; // ms 764b285192aSMauro Carvalho Chehab break; 765b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ENCORE_ENLTV_FM53: 766b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ENCORE_ENLTV_FM3: 767b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_ENCORE_ENLTV_FM53; 768b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ 769b285192aSMauro Carvalho Chehab mask_keyup = 0x0040000; 770b285192aSMauro Carvalho Chehab mask_keycode = 0xffff; 771b285192aSMauro Carvalho Chehab raw_decode = true; 772b285192aSMauro Carvalho Chehab break; 773b285192aSMauro Carvalho Chehab case SAA7134_BOARD_10MOONSTVMASTER3: 774b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_ENCORE_ENLTV; 775b285192aSMauro Carvalho Chehab mask_keycode = 0x5f80000; 776b285192aSMauro Carvalho Chehab mask_keyup = 0x8000000; 777b285192aSMauro Carvalho Chehab polling = 50; //ms 778b285192aSMauro Carvalho Chehab break; 779b285192aSMauro Carvalho Chehab case SAA7134_BOARD_GENIUS_TVGO_A11MCE: 780b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_GENIUS_TVGO_A11MCE; 781b285192aSMauro Carvalho Chehab mask_keycode = 0xff; 782b285192aSMauro Carvalho Chehab mask_keydown = 0xf00000; 783b285192aSMauro Carvalho Chehab polling = 50; /* ms */ 784b285192aSMauro Carvalho Chehab break; 785b285192aSMauro Carvalho Chehab case SAA7134_BOARD_REAL_ANGEL_220: 786b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_REAL_AUDIO_220_32_KEYS; 787b285192aSMauro Carvalho Chehab mask_keycode = 0x3f00; 788b285192aSMauro Carvalho Chehab mask_keyup = 0x4000; 789b285192aSMauro Carvalho Chehab polling = 50; /* ms */ 790b285192aSMauro Carvalho Chehab break; 791b285192aSMauro Carvalho Chehab case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG: 792b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_KWORLD_PLUS_TV_ANALOG; 793b285192aSMauro Carvalho Chehab mask_keycode = 0x7f; 794b285192aSMauro Carvalho Chehab polling = 40; /* ms */ 795b285192aSMauro Carvalho Chehab break; 796b285192aSMauro Carvalho Chehab case SAA7134_BOARD_VIDEOMATE_S350: 797b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_VIDEOMATE_S350; 798b285192aSMauro Carvalho Chehab mask_keycode = 0x003f00; 799b285192aSMauro Carvalho Chehab mask_keydown = 0x040000; 800b285192aSMauro Carvalho Chehab break; 801b285192aSMauro Carvalho Chehab case SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S: 802b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_WINFAST; 803b285192aSMauro Carvalho Chehab mask_keycode = 0x5f00; 804b285192aSMauro Carvalho Chehab mask_keyup = 0x020000; 805b285192aSMauro Carvalho Chehab polling = 50; /* ms */ 806b285192aSMauro Carvalho Chehab break; 807b285192aSMauro Carvalho Chehab case SAA7134_BOARD_VIDEOMATE_M1F: 808b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_VIDEOMATE_K100; 809b285192aSMauro Carvalho Chehab mask_keycode = 0x0ff00; 810b285192aSMauro Carvalho Chehab mask_keyup = 0x040000; 811b285192aSMauro Carvalho Chehab break; 812b285192aSMauro Carvalho Chehab case SAA7134_BOARD_HAUPPAUGE_HVR1150: 813b285192aSMauro Carvalho Chehab case SAA7134_BOARD_HAUPPAUGE_HVR1120: 814b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_HAUPPAUGE; 815b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ 816b285192aSMauro Carvalho Chehab mask_keyup = 0x0040000; 817b285192aSMauro Carvalho Chehab mask_keycode = 0xffff; 818b285192aSMauro Carvalho Chehab raw_decode = true; 819b285192aSMauro Carvalho Chehab break; 820b285192aSMauro Carvalho Chehab } 821b285192aSMauro Carvalho Chehab if (NULL == ir_codes) { 822b285192aSMauro Carvalho Chehab printk("%s: Oops: IR config error [card=%d]\n", 823b285192aSMauro Carvalho Chehab dev->name, dev->board); 824b285192aSMauro Carvalho Chehab return -ENODEV; 825b285192aSMauro Carvalho Chehab } 826b285192aSMauro Carvalho Chehab 827b285192aSMauro Carvalho Chehab ir = kzalloc(sizeof(*ir), GFP_KERNEL); 828b285192aSMauro Carvalho Chehab rc = rc_allocate_device(); 829b285192aSMauro Carvalho Chehab if (!ir || !rc) { 830b285192aSMauro Carvalho Chehab err = -ENOMEM; 831b285192aSMauro Carvalho Chehab goto err_out_free; 832b285192aSMauro Carvalho Chehab } 833b285192aSMauro Carvalho Chehab 834b285192aSMauro Carvalho Chehab ir->dev = rc; 835b285192aSMauro Carvalho Chehab dev->remote = ir; 836b285192aSMauro Carvalho Chehab 837b285192aSMauro Carvalho Chehab /* init hardware-specific stuff */ 838b285192aSMauro Carvalho Chehab ir->mask_keycode = mask_keycode; 839b285192aSMauro Carvalho Chehab ir->mask_keydown = mask_keydown; 840b285192aSMauro Carvalho Chehab ir->mask_keyup = mask_keyup; 841b285192aSMauro Carvalho Chehab ir->polling = polling; 842b285192aSMauro Carvalho Chehab ir->raw_decode = raw_decode; 843b285192aSMauro Carvalho Chehab 844b285192aSMauro Carvalho Chehab /* init input device */ 845b285192aSMauro Carvalho Chehab snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)", 846b285192aSMauro Carvalho Chehab saa7134_boards[dev->board].name); 847b285192aSMauro Carvalho Chehab snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", 848b285192aSMauro Carvalho Chehab pci_name(dev->pci)); 849b285192aSMauro Carvalho Chehab 850b285192aSMauro Carvalho Chehab rc->priv = dev; 851b285192aSMauro Carvalho Chehab rc->open = saa7134_ir_open; 852b285192aSMauro Carvalho Chehab rc->close = saa7134_ir_close; 853b285192aSMauro Carvalho Chehab if (raw_decode) 854b285192aSMauro Carvalho Chehab rc->driver_type = RC_DRIVER_IR_RAW; 855b285192aSMauro Carvalho Chehab 856b285192aSMauro Carvalho Chehab rc->input_name = ir->name; 857b285192aSMauro Carvalho Chehab rc->input_phys = ir->phys; 858b285192aSMauro Carvalho Chehab rc->input_id.bustype = BUS_PCI; 859b285192aSMauro Carvalho Chehab rc->input_id.version = 1; 860b285192aSMauro Carvalho Chehab if (dev->pci->subsystem_vendor) { 861b285192aSMauro Carvalho Chehab rc->input_id.vendor = dev->pci->subsystem_vendor; 862b285192aSMauro Carvalho Chehab rc->input_id.product = dev->pci->subsystem_device; 863b285192aSMauro Carvalho Chehab } else { 864b285192aSMauro Carvalho Chehab rc->input_id.vendor = dev->pci->vendor; 865b285192aSMauro Carvalho Chehab rc->input_id.product = dev->pci->device; 866b285192aSMauro Carvalho Chehab } 867b285192aSMauro Carvalho Chehab rc->dev.parent = &dev->pci->dev; 868b285192aSMauro Carvalho Chehab rc->map_name = ir_codes; 869b285192aSMauro Carvalho Chehab rc->driver_name = MODULE_NAME; 870b285192aSMauro Carvalho Chehab 871b285192aSMauro Carvalho Chehab err = rc_register_device(rc); 872b285192aSMauro Carvalho Chehab if (err) 873b285192aSMauro Carvalho Chehab goto err_out_free; 874b285192aSMauro Carvalho Chehab 875b285192aSMauro Carvalho Chehab return 0; 876b285192aSMauro Carvalho Chehab 877b285192aSMauro Carvalho Chehab err_out_free: 878b285192aSMauro Carvalho Chehab rc_free_device(rc); 879b285192aSMauro Carvalho Chehab dev->remote = NULL; 880b285192aSMauro Carvalho Chehab kfree(ir); 881b285192aSMauro Carvalho Chehab return err; 882b285192aSMauro Carvalho Chehab } 883b285192aSMauro Carvalho Chehab 884b285192aSMauro Carvalho Chehab void saa7134_input_fini(struct saa7134_dev *dev) 885b285192aSMauro Carvalho Chehab { 886b285192aSMauro Carvalho Chehab if (NULL == dev->remote) 887b285192aSMauro Carvalho Chehab return; 888b285192aSMauro Carvalho Chehab 889b285192aSMauro Carvalho Chehab saa7134_ir_stop(dev); 890b285192aSMauro Carvalho Chehab rc_unregister_device(dev->remote->dev); 891b285192aSMauro Carvalho Chehab kfree(dev->remote); 892b285192aSMauro Carvalho Chehab dev->remote = NULL; 893b285192aSMauro Carvalho Chehab } 894b285192aSMauro Carvalho Chehab 895b285192aSMauro Carvalho Chehab void saa7134_probe_i2c_ir(struct saa7134_dev *dev) 896b285192aSMauro Carvalho Chehab { 897b285192aSMauro Carvalho Chehab struct i2c_board_info info; 898b285192aSMauro Carvalho Chehab struct i2c_msg msg_msi = { 899b285192aSMauro Carvalho Chehab .addr = 0x50, 900b285192aSMauro Carvalho Chehab .flags = I2C_M_RD, 901b285192aSMauro Carvalho Chehab .len = 0, 902b285192aSMauro Carvalho Chehab .buf = NULL, 903b285192aSMauro Carvalho Chehab }; 904b285192aSMauro Carvalho Chehab int rc; 905b285192aSMauro Carvalho Chehab 906b285192aSMauro Carvalho Chehab if (disable_ir) { 907b285192aSMauro Carvalho Chehab dprintk("IR has been disabled, not probing for i2c remote\n"); 908b285192aSMauro Carvalho Chehab return; 909b285192aSMauro Carvalho Chehab } 910b285192aSMauro Carvalho Chehab 911b285192aSMauro Carvalho Chehab memset(&info, 0, sizeof(struct i2c_board_info)); 912b285192aSMauro Carvalho Chehab memset(&dev->init_data, 0, sizeof(dev->init_data)); 913b285192aSMauro Carvalho Chehab strlcpy(info.type, "ir_video", I2C_NAME_SIZE); 914b285192aSMauro Carvalho Chehab 915b285192aSMauro Carvalho Chehab switch (dev->board) { 916b285192aSMauro Carvalho Chehab case SAA7134_BOARD_PINNACLE_PCTV_110i: 917b285192aSMauro Carvalho Chehab case SAA7134_BOARD_PINNACLE_PCTV_310i: 918b285192aSMauro Carvalho Chehab dev->init_data.name = "Pinnacle PCTV"; 919b285192aSMauro Carvalho Chehab if (pinnacle_remote == 0) { 920b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_pinnacle_color; 921b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_PINNACLE_COLOR; 922b285192aSMauro Carvalho Chehab info.addr = 0x47; 923b285192aSMauro Carvalho Chehab } else { 924b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_pinnacle_grey; 925b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_PINNACLE_GREY; 926b285192aSMauro Carvalho Chehab info.addr = 0x47; 927b285192aSMauro Carvalho Chehab } 928b285192aSMauro Carvalho Chehab break; 929b285192aSMauro Carvalho Chehab case SAA7134_BOARD_UPMOST_PURPLE_TV: 930b285192aSMauro Carvalho Chehab dev->init_data.name = "Purple TV"; 931b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_purpletv; 932b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_PURPLETV; 933b285192aSMauro Carvalho Chehab info.addr = 0x7a; 934b285192aSMauro Carvalho Chehab break; 935b285192aSMauro Carvalho Chehab case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS: 936b285192aSMauro Carvalho Chehab dev->init_data.name = "MSI TV@nywhere Plus"; 937b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_msi_tvanywhere_plus; 938b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_MSI_TVANYWHERE_PLUS; 939b285192aSMauro Carvalho Chehab /* 940b285192aSMauro Carvalho Chehab * MSI TV@nyware Plus requires more frequent polling 941b285192aSMauro Carvalho Chehab * otherwise it will miss some keypresses 942b285192aSMauro Carvalho Chehab */ 943b285192aSMauro Carvalho Chehab dev->init_data.polling_interval = 50; 944b285192aSMauro Carvalho Chehab info.addr = 0x30; 945b285192aSMauro Carvalho Chehab /* MSI TV@nywhere Plus controller doesn't seem to 946b285192aSMauro Carvalho Chehab respond to probes unless we read something from 947b285192aSMauro Carvalho Chehab an existing device. Weird... 948b285192aSMauro Carvalho Chehab REVISIT: might no longer be needed */ 949b285192aSMauro Carvalho Chehab rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1); 950b285192aSMauro Carvalho Chehab dprintk("probe 0x%02x @ %s: %s\n", 951b285192aSMauro Carvalho Chehab msg_msi.addr, dev->i2c_adap.name, 952b285192aSMauro Carvalho Chehab (1 == rc) ? "yes" : "no"); 953b285192aSMauro Carvalho Chehab break; 954b285192aSMauro Carvalho Chehab case SAA7134_BOARD_KWORLD_PC150U: 955b285192aSMauro Carvalho Chehab /* copied and modified from MSI TV@nywhere Plus */ 956b285192aSMauro Carvalho Chehab dev->init_data.name = "Kworld PC150-U"; 957b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_kworld_pc150u; 958b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_KWORLD_PC150U; 959b285192aSMauro Carvalho Chehab info.addr = 0x30; 960b285192aSMauro Carvalho Chehab /* MSI TV@nywhere Plus controller doesn't seem to 961b285192aSMauro Carvalho Chehab respond to probes unless we read something from 962b285192aSMauro Carvalho Chehab an existing device. Weird... 963b285192aSMauro Carvalho Chehab REVISIT: might no longer be needed */ 964b285192aSMauro Carvalho Chehab rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1); 965b285192aSMauro Carvalho Chehab dprintk("probe 0x%02x @ %s: %s\n", 966b285192aSMauro Carvalho Chehab msg_msi.addr, dev->i2c_adap.name, 967b285192aSMauro Carvalho Chehab (1 == rc) ? "yes" : "no"); 968b285192aSMauro Carvalho Chehab break; 969b285192aSMauro Carvalho Chehab case SAA7134_BOARD_HAUPPAUGE_HVR1110: 970b285192aSMauro Carvalho Chehab dev->init_data.name = "HVR 1110"; 971b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_hvr1110; 972b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_HAUPPAUGE; 973b285192aSMauro Carvalho Chehab info.addr = 0x71; 974b285192aSMauro Carvalho Chehab break; 975b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_607FM_MK3: 976b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_607FM_MK5: 977b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_609FM_MK3: 978b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_609FM_MK5: 979b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_607RDS_MK3: 980b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_607RDS_MK5: 981b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_609RDS_MK3: 982b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_609RDS_MK5: 983b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_M6: 984b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_M63: 985b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_M6_EXTRA: 986b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_H6: 987b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_X7: 988b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_H7: 989b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_A7: 990b285192aSMauro Carvalho Chehab dev->init_data.name = "BeholdTV"; 991b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_beholdm6xx; 992b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_BEHOLD; 993c003ab1bSDavid Härdeman dev->init_data.type = RC_BIT_NEC; 994b285192aSMauro Carvalho Chehab info.addr = 0x2d; 995b285192aSMauro Carvalho Chehab break; 996b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_CARDBUS_501: 997b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: 998b285192aSMauro Carvalho Chehab info.addr = 0x40; 999b285192aSMauro Carvalho Chehab break; 1000b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYDVB_TRIO: 1001b285192aSMauro Carvalho Chehab dev->init_data.name = "FlyDVB Trio"; 1002b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_flydvb_trio; 1003b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_FLYDVB; 1004b285192aSMauro Carvalho Chehab info.addr = 0x0b; 1005b285192aSMauro Carvalho Chehab break; 1006b285192aSMauro Carvalho Chehab default: 1007b285192aSMauro Carvalho Chehab dprintk("No I2C IR support for board %x\n", dev->board); 1008b285192aSMauro Carvalho Chehab return; 1009b285192aSMauro Carvalho Chehab } 1010b285192aSMauro Carvalho Chehab 1011b285192aSMauro Carvalho Chehab if (dev->init_data.name) 1012b285192aSMauro Carvalho Chehab info.platform_data = &dev->init_data; 1013b285192aSMauro Carvalho Chehab i2c_new_device(&dev->i2c_adap, &info); 1014b285192aSMauro Carvalho Chehab } 1015b285192aSMauro Carvalho Chehab 1016b285192aSMauro Carvalho Chehab static int saa7134_raw_decode_irq(struct saa7134_dev *dev) 1017b285192aSMauro Carvalho Chehab { 1018b285192aSMauro Carvalho Chehab struct saa7134_card_ir *ir = dev->remote; 1019b285192aSMauro Carvalho Chehab unsigned long timeout; 1020b285192aSMauro Carvalho Chehab int space; 1021b285192aSMauro Carvalho Chehab 1022b285192aSMauro Carvalho Chehab /* Generate initial event */ 1023b285192aSMauro Carvalho Chehab saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 1024b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 1025b285192aSMauro Carvalho Chehab space = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown; 1026b285192aSMauro Carvalho Chehab ir_raw_event_store_edge(dev->remote->dev, space ? IR_SPACE : IR_PULSE); 1027b285192aSMauro Carvalho Chehab 1028b285192aSMauro Carvalho Chehab /* 1029b285192aSMauro Carvalho Chehab * Wait 15 ms from the start of the first IR event before processing 1030b285192aSMauro Carvalho Chehab * the event. This time is enough for NEC protocol. May need adjustments 1031b285192aSMauro Carvalho Chehab * to work with other protocols. 1032b285192aSMauro Carvalho Chehab */ 1033b285192aSMauro Carvalho Chehab smp_mb(); 1034b285192aSMauro Carvalho Chehab 1035b285192aSMauro Carvalho Chehab if (!timer_pending(&ir->timer)) { 1036b285192aSMauro Carvalho Chehab timeout = jiffies + msecs_to_jiffies(15); 1037b285192aSMauro Carvalho Chehab mod_timer(&ir->timer, timeout); 1038b285192aSMauro Carvalho Chehab } 1039b285192aSMauro Carvalho Chehab 1040b285192aSMauro Carvalho Chehab return 1; 1041b285192aSMauro Carvalho Chehab } 1042