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 */ 16b285192aSMauro Carvalho Chehab 179a12ccfcSMauro Carvalho Chehab #include "saa7134.h" 189a12ccfcSMauro Carvalho Chehab #include "saa7134-reg.h" 199a12ccfcSMauro Carvalho Chehab 20b285192aSMauro Carvalho Chehab #include <linux/module.h> 21b285192aSMauro Carvalho Chehab #include <linux/init.h> 22b285192aSMauro Carvalho Chehab #include <linux/delay.h> 23b285192aSMauro Carvalho Chehab #include <linux/interrupt.h> 24b285192aSMauro Carvalho Chehab #include <linux/slab.h> 25b285192aSMauro Carvalho Chehab 26b285192aSMauro Carvalho Chehab #define MODULE_NAME "saa7134" 27b285192aSMauro Carvalho Chehab 28b285192aSMauro Carvalho Chehab static unsigned int disable_ir; 29b285192aSMauro Carvalho Chehab module_param(disable_ir, int, 0444); 30b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(disable_ir,"disable infrared remote support"); 31b285192aSMauro Carvalho Chehab 32b285192aSMauro Carvalho Chehab static unsigned int ir_debug; 33b285192aSMauro Carvalho Chehab module_param(ir_debug, int, 0644); 34b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]"); 35b285192aSMauro Carvalho Chehab 36b285192aSMauro Carvalho Chehab static int pinnacle_remote; 37b285192aSMauro Carvalho Chehab module_param(pinnacle_remote, int, 0644); /* Choose Pinnacle PCTV remote */ 38b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(pinnacle_remote, "Specify Pinnacle PCTV remote: 0=coloured, 1=grey (defaults to 0)"); 39b285192aSMauro Carvalho Chehab 4045f38cb3SMauro Carvalho Chehab #define input_dbg(fmt, arg...) do { \ 4145f38cb3SMauro Carvalho Chehab if (ir_debug) \ 4245f38cb3SMauro Carvalho Chehab printk(KERN_DEBUG pr_fmt("input: " fmt), ## arg); \ 4345f38cb3SMauro Carvalho Chehab } while (0) 4445f38cb3SMauro Carvalho Chehab #define ir_dbg(ir, fmt, arg...) do { \ 4545f38cb3SMauro Carvalho Chehab if (ir_debug) \ 4645f38cb3SMauro Carvalho Chehab printk(KERN_DEBUG pr_fmt("ir %s: " fmt), ir->name, ## arg); \ 4745f38cb3SMauro Carvalho Chehab } while (0) 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); 786be5b1a1SMauro Carvalho Chehab input_dbg("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 866d741bfeSSean Young rc_keydown_notimeout(ir->dev, RC_PROTO_UNKNOWN, data, 876d741bfeSSean Young 0); 88b285192aSMauro Carvalho Chehab return 0; 89b285192aSMauro Carvalho Chehab } 90b285192aSMauro Carvalho Chehab 91b285192aSMauro Carvalho Chehab if (ir->polling) { 92b285192aSMauro Carvalho Chehab if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) || 93b285192aSMauro Carvalho Chehab (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { 946d741bfeSSean Young rc_keydown_notimeout(ir->dev, RC_PROTO_UNKNOWN, data, 956d741bfeSSean Young 0); 96b285192aSMauro Carvalho Chehab } else { 97b285192aSMauro Carvalho Chehab rc_keyup(ir->dev); 98b285192aSMauro Carvalho Chehab } 99b285192aSMauro Carvalho Chehab } 100b285192aSMauro Carvalho Chehab else { /* IRQ driven mode - handle key press and release in one go */ 101b285192aSMauro Carvalho Chehab if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) || 102b285192aSMauro Carvalho Chehab (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { 1036d741bfeSSean Young rc_keydown_notimeout(ir->dev, RC_PROTO_UNKNOWN, data, 1046d741bfeSSean Young 0); 105b285192aSMauro Carvalho Chehab rc_keyup(ir->dev); 106b285192aSMauro Carvalho Chehab } 107b285192aSMauro Carvalho Chehab } 108b285192aSMauro Carvalho Chehab 109b285192aSMauro Carvalho Chehab return 0; 110b285192aSMauro Carvalho Chehab } 111b285192aSMauro Carvalho Chehab 112b285192aSMauro Carvalho Chehab /* --------------------- Chip specific I2C key builders ----------------- */ 113b285192aSMauro Carvalho Chehab 1146d741bfeSSean Young static int get_key_flydvb_trio(struct IR_i2c *ir, enum rc_proto *protocol, 1154dd9bb91SDavid Härdeman u32 *scancode, u8 *toggle) 116b285192aSMauro Carvalho Chehab { 117b285192aSMauro Carvalho Chehab int gpio; 118b285192aSMauro Carvalho Chehab int attempt = 0; 119b285192aSMauro Carvalho Chehab unsigned char b; 120b285192aSMauro Carvalho Chehab 121b285192aSMauro Carvalho Chehab /* We need this to access GPI Used by the saa_readl macro. */ 122b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = ir->c->adapter->algo_data; 123b285192aSMauro Carvalho Chehab 124b285192aSMauro Carvalho Chehab if (dev == NULL) { 125395eff95SMauro Carvalho Chehab ir_dbg(ir, "get_key_flydvb_trio: ir->c->adapter->algo_data is NULL!\n"); 126b285192aSMauro Carvalho Chehab return -EIO; 127b285192aSMauro Carvalho Chehab } 128b285192aSMauro Carvalho Chehab 129b285192aSMauro Carvalho Chehab /* rising SAA7134_GPIGPRESCAN reads the status */ 130b285192aSMauro Carvalho Chehab saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 131b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 132b285192aSMauro Carvalho Chehab 133b285192aSMauro Carvalho Chehab gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2); 134b285192aSMauro Carvalho Chehab 135b285192aSMauro Carvalho Chehab if (0x40000 & ~gpio) 136b285192aSMauro Carvalho Chehab return 0; /* No button press */ 137b285192aSMauro Carvalho Chehab 138b285192aSMauro Carvalho Chehab /* poll IR chip */ 139b285192aSMauro Carvalho Chehab /* weak up the IR chip */ 140b285192aSMauro Carvalho Chehab b = 0; 141b285192aSMauro Carvalho Chehab 142b285192aSMauro Carvalho Chehab while (1 != i2c_master_send(ir->c, &b, 1)) { 143b285192aSMauro Carvalho Chehab if ((attempt++) < 10) { 144b285192aSMauro Carvalho Chehab /* 145b285192aSMauro Carvalho Chehab * wait a bit for next attempt - 146b285192aSMauro Carvalho Chehab * I don't know how make it better 147b285192aSMauro Carvalho Chehab */ 148b285192aSMauro Carvalho Chehab msleep(10); 149b285192aSMauro Carvalho Chehab continue; 150b285192aSMauro Carvalho Chehab } 151395eff95SMauro Carvalho Chehab ir_dbg(ir, "send wake up byte to pic16C505 (IR chip)failed %dx\n", 152395eff95SMauro Carvalho Chehab attempt); 153b285192aSMauro Carvalho Chehab return -EIO; 154b285192aSMauro Carvalho Chehab } 155b285192aSMauro Carvalho Chehab if (1 != i2c_master_recv(ir->c, &b, 1)) { 1566be5b1a1SMauro Carvalho Chehab ir_dbg(ir, "read error\n"); 157b285192aSMauro Carvalho Chehab return -EIO; 158b285192aSMauro Carvalho Chehab } 159b285192aSMauro Carvalho Chehab 1606d741bfeSSean Young *protocol = RC_PROTO_UNKNOWN; 1614dd9bb91SDavid Härdeman *scancode = b; 1624dd9bb91SDavid Härdeman *toggle = 0; 163b285192aSMauro Carvalho Chehab return 1; 164b285192aSMauro Carvalho Chehab } 165b285192aSMauro Carvalho Chehab 1666d741bfeSSean Young static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, 1676d741bfeSSean Young enum rc_proto *protocol, 1684dd9bb91SDavid Härdeman u32 *scancode, u8 *toggle) 169b285192aSMauro Carvalho Chehab { 170b285192aSMauro Carvalho Chehab unsigned char b; 171b285192aSMauro Carvalho Chehab int gpio; 172b285192aSMauro Carvalho Chehab 173b285192aSMauro Carvalho Chehab /* <dev> is needed to access GPIO. Used by the saa_readl macro. */ 174b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = ir->c->adapter->algo_data; 175b285192aSMauro Carvalho Chehab if (dev == NULL) { 176395eff95SMauro Carvalho Chehab ir_dbg(ir, "get_key_msi_tvanywhere_plus: 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)) { 1966be5b1a1SMauro Carvalho Chehab ir_dbg(ir, "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 2076be5b1a1SMauro Carvalho Chehab input_dbg("get_key_msi_tvanywhere_plus: Key = 0x%02X\n", b); 2086d741bfeSSean Young *protocol = RC_PROTO_UNKNOWN; 2094dd9bb91SDavid Härdeman *scancode = b; 2104dd9bb91SDavid Härdeman *toggle = 0; 211b285192aSMauro Carvalho Chehab return 1; 212b285192aSMauro Carvalho Chehab } 213b285192aSMauro Carvalho Chehab 214b285192aSMauro Carvalho Chehab /* copied and modified from get_key_msi_tvanywhere_plus() */ 2156d741bfeSSean Young static int get_key_kworld_pc150u(struct IR_i2c *ir, enum rc_proto *protocol, 2164dd9bb91SDavid Härdeman u32 *scancode, u8 *toggle) 217b285192aSMauro Carvalho Chehab { 218b285192aSMauro Carvalho Chehab unsigned char b; 219b285192aSMauro Carvalho Chehab unsigned int gpio; 220b285192aSMauro Carvalho Chehab 221b285192aSMauro Carvalho Chehab /* <dev> is needed to access GPIO. Used by the saa_readl macro. */ 222b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = ir->c->adapter->algo_data; 223b285192aSMauro Carvalho Chehab if (dev == NULL) { 224395eff95SMauro Carvalho Chehab ir_dbg(ir, "get_key_kworld_pc150u: 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)) { 2446be5b1a1SMauro Carvalho Chehab ir_dbg(ir, "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 2556be5b1a1SMauro Carvalho Chehab input_dbg("get_key_kworld_pc150u: Key = 0x%02X\n", b); 2566d741bfeSSean Young *protocol = RC_PROTO_UNKNOWN; 2574dd9bb91SDavid Härdeman *scancode = b; 2584dd9bb91SDavid Härdeman *toggle = 0; 259b285192aSMauro Carvalho Chehab return 1; 260b285192aSMauro Carvalho Chehab } 261b285192aSMauro Carvalho Chehab 2626d741bfeSSean Young static int get_key_purpletv(struct IR_i2c *ir, enum rc_proto *protocol, 2634dd9bb91SDavid Härdeman u32 *scancode, u8 *toggle) 264b285192aSMauro Carvalho Chehab { 265b285192aSMauro Carvalho Chehab unsigned char b; 266b285192aSMauro Carvalho Chehab 267b285192aSMauro Carvalho Chehab /* poll IR chip */ 268b285192aSMauro Carvalho Chehab if (1 != i2c_master_recv(ir->c, &b, 1)) { 2696be5b1a1SMauro Carvalho Chehab ir_dbg(ir, "read error\n"); 270b285192aSMauro Carvalho Chehab return -EIO; 271b285192aSMauro Carvalho Chehab } 272b285192aSMauro Carvalho Chehab 273b285192aSMauro Carvalho Chehab /* no button press */ 274b285192aSMauro Carvalho Chehab if (b==0) 275b285192aSMauro Carvalho Chehab return 0; 276b285192aSMauro Carvalho Chehab 277b285192aSMauro Carvalho Chehab /* repeating */ 278b285192aSMauro Carvalho Chehab if (b & 0x80) 279b285192aSMauro Carvalho Chehab return 1; 280b285192aSMauro Carvalho Chehab 2816d741bfeSSean Young *protocol = RC_PROTO_UNKNOWN; 2824dd9bb91SDavid Härdeman *scancode = b; 2834dd9bb91SDavid Härdeman *toggle = 0; 284b285192aSMauro Carvalho Chehab return 1; 285b285192aSMauro Carvalho Chehab } 286b285192aSMauro Carvalho Chehab 2876d741bfeSSean Young static int get_key_hvr1110(struct IR_i2c *ir, enum rc_proto *protocol, 2884dd9bb91SDavid Härdeman u32 *scancode, u8 *toggle) 289b285192aSMauro Carvalho Chehab { 290b285192aSMauro Carvalho Chehab unsigned char buf[5]; 291b285192aSMauro Carvalho Chehab 292b285192aSMauro Carvalho Chehab /* poll IR chip */ 293b285192aSMauro Carvalho Chehab if (5 != i2c_master_recv(ir->c, buf, 5)) 294b285192aSMauro Carvalho Chehab return -EIO; 295b285192aSMauro Carvalho Chehab 296b285192aSMauro Carvalho Chehab /* Check if some key were pressed */ 297b285192aSMauro Carvalho Chehab if (!(buf[0] & 0x80)) 298b285192aSMauro Carvalho Chehab return 0; 299b285192aSMauro Carvalho Chehab 300b285192aSMauro Carvalho Chehab /* 301b285192aSMauro Carvalho Chehab * buf[3] & 0x80 is always high. 302b285192aSMauro Carvalho Chehab * buf[3] & 0x40 is a parity bit. A repeat event is marked 303b285192aSMauro Carvalho Chehab * by preserving it into two separate readings 304b285192aSMauro Carvalho Chehab * buf[4] bits 0 and 1, and buf[1] and buf[2] are always 305b285192aSMauro Carvalho Chehab * zero. 3064dd9bb91SDavid Härdeman * 3074dd9bb91SDavid Härdeman * Note that the keymap which the hvr1110 uses is RC5. 3084dd9bb91SDavid Härdeman * 3094dd9bb91SDavid Härdeman * FIXME: start bits could maybe be used...? 310b285192aSMauro Carvalho Chehab */ 3116d741bfeSSean Young *protocol = RC_PROTO_RC5; 3124dd9bb91SDavid Härdeman *scancode = RC_SCANCODE_RC5(buf[3] & 0x1f, buf[4] >> 2); 3134dd9bb91SDavid Härdeman *toggle = !!(buf[3] & 0x40); 314b285192aSMauro Carvalho Chehab return 1; 315b285192aSMauro Carvalho Chehab } 316b285192aSMauro Carvalho Chehab 317b285192aSMauro Carvalho Chehab 3186d741bfeSSean Young static int get_key_beholdm6xx(struct IR_i2c *ir, enum rc_proto *protocol, 3194dd9bb91SDavid Härdeman u32 *scancode, u8 *toggle) 320b285192aSMauro Carvalho Chehab { 321b285192aSMauro Carvalho Chehab unsigned char data[12]; 322b285192aSMauro Carvalho Chehab u32 gpio; 323b285192aSMauro Carvalho Chehab 324b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = ir->c->adapter->algo_data; 325b285192aSMauro Carvalho Chehab 326b285192aSMauro Carvalho Chehab /* rising SAA7134_GPIO_GPRESCAN reads the status */ 327b285192aSMauro Carvalho Chehab saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 328b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 329b285192aSMauro Carvalho Chehab 330b285192aSMauro Carvalho Chehab gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2); 331b285192aSMauro Carvalho Chehab 332b285192aSMauro Carvalho Chehab if (0x400000 & ~gpio) 333b285192aSMauro Carvalho Chehab return 0; /* No button press */ 334b285192aSMauro Carvalho Chehab 335b285192aSMauro Carvalho Chehab ir->c->addr = 0x5a >> 1; 336b285192aSMauro Carvalho Chehab 337b285192aSMauro Carvalho Chehab if (12 != i2c_master_recv(ir->c, data, 12)) { 3386be5b1a1SMauro Carvalho Chehab ir_dbg(ir, "read error\n"); 339b285192aSMauro Carvalho Chehab return -EIO; 340b285192aSMauro Carvalho Chehab } 341b285192aSMauro Carvalho Chehab 342b285192aSMauro Carvalho Chehab if (data[9] != (unsigned char)(~data[8])) 343b285192aSMauro Carvalho Chehab return 0; 344b285192aSMauro Carvalho Chehab 3456d741bfeSSean Young *protocol = RC_PROTO_NECX; 3460bc56cbeSDavid Härdeman *scancode = RC_SCANCODE_NECX(data[11] << 8 | data[10], data[9]); 3474dd9bb91SDavid Härdeman *toggle = 0; 348b285192aSMauro Carvalho Chehab return 1; 349b285192aSMauro Carvalho Chehab } 350b285192aSMauro Carvalho Chehab 351b285192aSMauro Carvalho Chehab /* Common (grey or coloured) pinnacle PCTV remote handling 352b285192aSMauro Carvalho Chehab * 353b285192aSMauro Carvalho Chehab */ 3546d741bfeSSean Young static int get_key_pinnacle(struct IR_i2c *ir, enum rc_proto *protocol, 3554dd9bb91SDavid Härdeman u32 *scancode, u8 *toggle, int parity_offset, 3564dd9bb91SDavid Härdeman int marker, int code_modulo) 357b285192aSMauro Carvalho Chehab { 358b285192aSMauro Carvalho Chehab unsigned char b[4]; 359b285192aSMauro Carvalho Chehab unsigned int start = 0,parity = 0,code = 0; 360b285192aSMauro Carvalho Chehab 361b285192aSMauro Carvalho Chehab /* poll IR chip */ 362b285192aSMauro Carvalho Chehab if (4 != i2c_master_recv(ir->c, b, 4)) { 3636be5b1a1SMauro Carvalho Chehab ir_dbg(ir, "read error\n"); 364b285192aSMauro Carvalho Chehab return -EIO; 365b285192aSMauro Carvalho Chehab } 366b285192aSMauro Carvalho Chehab 367b285192aSMauro Carvalho Chehab for (start = 0; start < ARRAY_SIZE(b); start++) { 368b285192aSMauro Carvalho Chehab if (b[start] == marker) { 369b285192aSMauro Carvalho Chehab code=b[(start+parity_offset + 1) % 4]; 370b285192aSMauro Carvalho Chehab parity=b[(start+parity_offset) % 4]; 371b285192aSMauro Carvalho Chehab } 372b285192aSMauro Carvalho Chehab } 373b285192aSMauro Carvalho Chehab 374b285192aSMauro Carvalho Chehab /* Empty Request */ 375b285192aSMauro Carvalho Chehab if (parity == 0) 376b285192aSMauro Carvalho Chehab return 0; 377b285192aSMauro Carvalho Chehab 378b285192aSMauro Carvalho Chehab /* Repeating... */ 379b285192aSMauro Carvalho Chehab if (ir->old == parity) 380b285192aSMauro Carvalho Chehab return 0; 381b285192aSMauro Carvalho Chehab 382b285192aSMauro Carvalho Chehab ir->old = parity; 383b285192aSMauro Carvalho Chehab 384b285192aSMauro Carvalho Chehab /* drop special codes when a key is held down a long time for the grey controller 385b285192aSMauro Carvalho Chehab In this case, the second bit of the code is asserted */ 386b285192aSMauro Carvalho Chehab if (marker == 0xfe && (code & 0x40)) 387b285192aSMauro Carvalho Chehab return 0; 388b285192aSMauro Carvalho Chehab 389b285192aSMauro Carvalho Chehab code %= code_modulo; 390b285192aSMauro Carvalho Chehab 3916d741bfeSSean Young *protocol = RC_PROTO_UNKNOWN; 3924dd9bb91SDavid Härdeman *scancode = code; 3934dd9bb91SDavid Härdeman *toggle = 0; 394b285192aSMauro Carvalho Chehab 3956be5b1a1SMauro Carvalho Chehab ir_dbg(ir, "Pinnacle PCTV key %02x\n", code); 396b285192aSMauro Carvalho Chehab return 1; 397b285192aSMauro Carvalho Chehab } 398b285192aSMauro Carvalho Chehab 399b285192aSMauro Carvalho Chehab /* The grey pinnacle PCTV remote 400b285192aSMauro Carvalho Chehab * 401b285192aSMauro Carvalho Chehab * There are one issue with this remote: 402b285192aSMauro Carvalho Chehab * - I2c packet does not change when the same key is pressed quickly. The workaround 403b285192aSMauro Carvalho Chehab * is to hold down each key for about half a second, so that another code is generated 404b285192aSMauro Carvalho Chehab * in the i2c packet, and the function can distinguish key presses. 405b285192aSMauro Carvalho Chehab * 406b285192aSMauro Carvalho Chehab * Sylvain Pasche <sylvain.pasche@gmail.com> 407b285192aSMauro Carvalho Chehab */ 4086d741bfeSSean Young static int get_key_pinnacle_grey(struct IR_i2c *ir, enum rc_proto *protocol, 4094dd9bb91SDavid Härdeman u32 *scancode, u8 *toggle) 410b285192aSMauro Carvalho Chehab { 411b285192aSMauro Carvalho Chehab 4124dd9bb91SDavid Härdeman return get_key_pinnacle(ir, protocol, scancode, toggle, 1, 0xfe, 0xff); 413b285192aSMauro Carvalho Chehab } 414b285192aSMauro Carvalho Chehab 415b285192aSMauro Carvalho Chehab 416b285192aSMauro Carvalho Chehab /* The new pinnacle PCTV remote (with the colored buttons) 417b285192aSMauro Carvalho Chehab * 418b285192aSMauro Carvalho Chehab * Ricardo Cerqueira <v4l@cerqueira.org> 419b285192aSMauro Carvalho Chehab */ 4206d741bfeSSean Young static int get_key_pinnacle_color(struct IR_i2c *ir, enum rc_proto *protocol, 4214dd9bb91SDavid Härdeman u32 *scancode, u8 *toggle) 422b285192aSMauro Carvalho Chehab { 423b285192aSMauro Carvalho Chehab /* code_modulo parameter (0x88) is used to reduce code value to fit inside IR_KEYTAB_SIZE 424b285192aSMauro Carvalho Chehab * 425b285192aSMauro Carvalho Chehab * this is the only value that results in 42 unique 426b285192aSMauro Carvalho Chehab * codes < 128 427b285192aSMauro Carvalho Chehab */ 428b285192aSMauro Carvalho Chehab 4294dd9bb91SDavid Härdeman return get_key_pinnacle(ir, protocol, scancode, toggle, 2, 0x80, 0x88); 430b285192aSMauro Carvalho Chehab } 431b285192aSMauro Carvalho Chehab 432b285192aSMauro Carvalho Chehab void saa7134_input_irq(struct saa7134_dev *dev) 433b285192aSMauro Carvalho Chehab { 434b285192aSMauro Carvalho Chehab struct saa7134_card_ir *ir; 435b285192aSMauro Carvalho Chehab 436b285192aSMauro Carvalho Chehab if (!dev || !dev->remote) 437b285192aSMauro Carvalho Chehab return; 438b285192aSMauro Carvalho Chehab 439b285192aSMauro Carvalho Chehab ir = dev->remote; 440b285192aSMauro Carvalho Chehab if (!ir->running) 441b285192aSMauro Carvalho Chehab return; 442b285192aSMauro Carvalho Chehab 443b285192aSMauro Carvalho Chehab if (!ir->polling && !ir->raw_decode) { 444b285192aSMauro Carvalho Chehab build_key(dev); 445b285192aSMauro Carvalho Chehab } else if (ir->raw_decode) { 446b285192aSMauro Carvalho Chehab saa7134_raw_decode_irq(dev); 447b285192aSMauro Carvalho Chehab } 448b285192aSMauro Carvalho Chehab } 449b285192aSMauro Carvalho Chehab 450b285192aSMauro Carvalho Chehab static void saa7134_input_timer(unsigned long data) 451b285192aSMauro Carvalho Chehab { 452b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = (struct saa7134_dev *)data; 453b285192aSMauro Carvalho Chehab struct saa7134_card_ir *ir = dev->remote; 454b285192aSMauro Carvalho Chehab 455b285192aSMauro Carvalho Chehab build_key(dev); 456b285192aSMauro Carvalho Chehab mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); 457b285192aSMauro Carvalho Chehab } 458b285192aSMauro Carvalho Chehab 459b285192aSMauro Carvalho Chehab static int __saa7134_ir_start(void *priv) 460b285192aSMauro Carvalho Chehab { 461b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = priv; 462b285192aSMauro Carvalho Chehab struct saa7134_card_ir *ir; 463b285192aSMauro Carvalho Chehab 464b285192aSMauro Carvalho Chehab if (!dev || !dev->remote) 465b285192aSMauro Carvalho Chehab return -EINVAL; 466b285192aSMauro Carvalho Chehab 467b285192aSMauro Carvalho Chehab ir = dev->remote; 468b285192aSMauro Carvalho Chehab if (ir->running) 469b285192aSMauro Carvalho Chehab return 0; 470b285192aSMauro Carvalho Chehab 471b285192aSMauro Carvalho Chehab /* Moved here from saa7134_input_init1() because the latter 472b285192aSMauro Carvalho Chehab * is not called on device resume */ 473b285192aSMauro Carvalho Chehab switch (dev->board) { 474b285192aSMauro Carvalho Chehab case SAA7134_BOARD_MD2819: 475b285192aSMauro Carvalho Chehab case SAA7134_BOARD_KWORLD_VSTREAM_XPERT: 476b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_305: 477b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_307: 478de983454SDmitry Eremin-Solenikov case SAA7134_BOARD_AVERMEDIA_505: 479b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_305: 480b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_505: 481b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_307: 482b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_507: 483b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_507UA: 484b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_GO_007_FM: 485b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_M102: 486b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS: 487b285192aSMauro Carvalho Chehab /* Without this we won't receive key up events */ 488b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE0, 0x4); 489b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); 490b285192aSMauro Carvalho Chehab break; 491b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_777: 492b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_A16AR: 493b285192aSMauro Carvalho Chehab /* Without this we won't receive key up events */ 494b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE1, 0x1); 495b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1); 496b285192aSMauro Carvalho Chehab break; 497b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_A16D: 498b285192aSMauro Carvalho Chehab /* Without this we won't receive key up events */ 499b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE1, 0x1); 500b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1); 501b285192aSMauro Carvalho Chehab break; 502b285192aSMauro Carvalho Chehab case SAA7134_BOARD_GOTVIEW_7135: 503b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE1, 0x80); 504b285192aSMauro Carvalho Chehab break; 505b285192aSMauro Carvalho Chehab } 506b285192aSMauro Carvalho Chehab 507b285192aSMauro Carvalho Chehab ir->running = true; 508b285192aSMauro Carvalho Chehab 509b285192aSMauro Carvalho Chehab if (ir->polling) { 510b285192aSMauro Carvalho Chehab setup_timer(&ir->timer, saa7134_input_timer, 511b285192aSMauro Carvalho Chehab (unsigned long)dev); 512b285192aSMauro Carvalho Chehab ir->timer.expires = jiffies + HZ; 513b285192aSMauro Carvalho Chehab add_timer(&ir->timer); 514b285192aSMauro Carvalho Chehab } 515b285192aSMauro Carvalho Chehab 516b285192aSMauro Carvalho Chehab return 0; 517b285192aSMauro Carvalho Chehab } 518b285192aSMauro Carvalho Chehab 519b285192aSMauro Carvalho Chehab static void __saa7134_ir_stop(void *priv) 520b285192aSMauro Carvalho Chehab { 521b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = priv; 522b285192aSMauro Carvalho Chehab struct saa7134_card_ir *ir; 523b285192aSMauro Carvalho Chehab 524b285192aSMauro Carvalho Chehab if (!dev || !dev->remote) 525b285192aSMauro Carvalho Chehab return; 526b285192aSMauro Carvalho Chehab 527b285192aSMauro Carvalho Chehab ir = dev->remote; 528b285192aSMauro Carvalho Chehab if (!ir->running) 529b285192aSMauro Carvalho Chehab return; 530b285192aSMauro Carvalho Chehab 531e5e26439SSean Young if (ir->polling) 532b285192aSMauro Carvalho Chehab del_timer_sync(&ir->timer); 533b285192aSMauro Carvalho Chehab 534b285192aSMauro Carvalho Chehab ir->running = false; 535b285192aSMauro Carvalho Chehab 536b285192aSMauro Carvalho Chehab return; 537b285192aSMauro Carvalho Chehab } 538b285192aSMauro Carvalho Chehab 539b285192aSMauro Carvalho Chehab int saa7134_ir_start(struct saa7134_dev *dev) 540b285192aSMauro Carvalho Chehab { 541b285192aSMauro Carvalho Chehab if (dev->remote->users) 542b285192aSMauro Carvalho Chehab return __saa7134_ir_start(dev); 543b285192aSMauro Carvalho Chehab 544b285192aSMauro Carvalho Chehab return 0; 545b285192aSMauro Carvalho Chehab } 546b285192aSMauro Carvalho Chehab 547b285192aSMauro Carvalho Chehab void saa7134_ir_stop(struct saa7134_dev *dev) 548b285192aSMauro Carvalho Chehab { 549b285192aSMauro Carvalho Chehab if (dev->remote->users) 550b285192aSMauro Carvalho Chehab __saa7134_ir_stop(dev); 551b285192aSMauro Carvalho Chehab } 552b285192aSMauro Carvalho Chehab 553b285192aSMauro Carvalho Chehab static int saa7134_ir_open(struct rc_dev *rc) 554b285192aSMauro Carvalho Chehab { 555b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = rc->priv; 556b285192aSMauro Carvalho Chehab 557b285192aSMauro Carvalho Chehab dev->remote->users++; 558b285192aSMauro Carvalho Chehab return __saa7134_ir_start(dev); 559b285192aSMauro Carvalho Chehab } 560b285192aSMauro Carvalho Chehab 561b285192aSMauro Carvalho Chehab static void saa7134_ir_close(struct rc_dev *rc) 562b285192aSMauro Carvalho Chehab { 563b285192aSMauro Carvalho Chehab struct saa7134_dev *dev = rc->priv; 564b285192aSMauro Carvalho Chehab 565b285192aSMauro Carvalho Chehab dev->remote->users--; 566b285192aSMauro Carvalho Chehab if (!dev->remote->users) 567b285192aSMauro Carvalho Chehab __saa7134_ir_stop(dev); 568b285192aSMauro Carvalho Chehab } 569b285192aSMauro Carvalho Chehab 570b285192aSMauro Carvalho Chehab int saa7134_input_init1(struct saa7134_dev *dev) 571b285192aSMauro Carvalho Chehab { 572b285192aSMauro Carvalho Chehab struct saa7134_card_ir *ir; 573b285192aSMauro Carvalho Chehab struct rc_dev *rc; 574b285192aSMauro Carvalho Chehab char *ir_codes = NULL; 575b285192aSMauro Carvalho Chehab u32 mask_keycode = 0; 576b285192aSMauro Carvalho Chehab u32 mask_keydown = 0; 577b285192aSMauro Carvalho Chehab u32 mask_keyup = 0; 578b285192aSMauro Carvalho Chehab unsigned polling = 0; 579b285192aSMauro Carvalho Chehab bool raw_decode = false; 580b285192aSMauro Carvalho Chehab int err; 581b285192aSMauro Carvalho Chehab 582b285192aSMauro Carvalho Chehab if (dev->has_remote != SAA7134_REMOTE_GPIO) 583b285192aSMauro Carvalho Chehab return -ENODEV; 584b285192aSMauro Carvalho Chehab if (disable_ir) 585b285192aSMauro Carvalho Chehab return -ENODEV; 586b285192aSMauro Carvalho Chehab 587b285192aSMauro Carvalho Chehab /* detect & configure */ 588b285192aSMauro Carvalho Chehab switch (dev->board) { 589b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYVIDEO2000: 590b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYVIDEO3000: 591b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYTVPLATINUM_FM: 592b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYTVPLATINUM_MINI2: 593b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM: 594b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_FLYVIDEO; 595b285192aSMauro Carvalho Chehab mask_keycode = 0xEC00000; 596b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; 597b285192aSMauro Carvalho Chehab break; 598b285192aSMauro Carvalho Chehab case SAA7134_BOARD_CINERGY400: 599b285192aSMauro Carvalho Chehab case SAA7134_BOARD_CINERGY600: 600b285192aSMauro Carvalho Chehab case SAA7134_BOARD_CINERGY600_MK3: 601b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_CINERGY; 602b285192aSMauro Carvalho Chehab mask_keycode = 0x00003f; 603b285192aSMauro Carvalho Chehab mask_keyup = 0x040000; 604b285192aSMauro Carvalho Chehab break; 605b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ECS_TVP3XP: 606b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ECS_TVP3XP_4CB5: 607b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_EZTV; 608b285192aSMauro Carvalho Chehab mask_keycode = 0x00017c; 609b285192aSMauro Carvalho Chehab mask_keyup = 0x000002; 610b285192aSMauro Carvalho Chehab polling = 50; // ms 611b285192aSMauro Carvalho Chehab break; 612b285192aSMauro Carvalho Chehab case SAA7134_BOARD_KWORLD_XPERT: 613b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVACSSMARTTV: 614b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_PIXELVIEW; 615b285192aSMauro Carvalho Chehab mask_keycode = 0x00001F; 616b285192aSMauro Carvalho Chehab mask_keyup = 0x000020; 617b285192aSMauro Carvalho Chehab polling = 50; // ms 618b285192aSMauro Carvalho Chehab break; 619b285192aSMauro Carvalho Chehab case SAA7134_BOARD_MD2819: 620b285192aSMauro Carvalho Chehab case SAA7134_BOARD_KWORLD_VSTREAM_XPERT: 621b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_305: 622b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_307: 623de983454SDmitry Eremin-Solenikov case SAA7134_BOARD_AVERMEDIA_505: 624b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_305: 625b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_505: 626b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_307: 627b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_507: 628b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_STUDIO_507UA: 629b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_GO_007_FM: 630b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_M102: 631b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS: 632b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_AVERMEDIA; 633b285192aSMauro Carvalho Chehab mask_keycode = 0x0007C8; 634b285192aSMauro Carvalho Chehab mask_keydown = 0x000010; 635b285192aSMauro Carvalho Chehab polling = 50; // ms 636b285192aSMauro Carvalho Chehab /* GPIO stuff moved to __saa7134_ir_start() */ 637b285192aSMauro Carvalho Chehab break; 638b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_M135A: 639b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_AVERMEDIA_M135A; 640b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ 641b285192aSMauro Carvalho Chehab mask_keyup = 0x0040000; 642b285192aSMauro Carvalho Chehab mask_keycode = 0xffff; 643b285192aSMauro Carvalho Chehab raw_decode = true; 644b285192aSMauro Carvalho Chehab break; 645b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_M733A: 646b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_AVERMEDIA_M733A_RM_K6; 647b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; 648b285192aSMauro Carvalho Chehab mask_keyup = 0x0040000; 649b285192aSMauro Carvalho Chehab mask_keycode = 0xffff; 650b285192aSMauro Carvalho Chehab raw_decode = true; 651b285192aSMauro Carvalho Chehab break; 652b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_777: 653b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_A16AR: 654b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_AVERMEDIA; 655b285192aSMauro Carvalho Chehab mask_keycode = 0x02F200; 656b285192aSMauro Carvalho Chehab mask_keydown = 0x000400; 657b285192aSMauro Carvalho Chehab polling = 50; // ms 658b285192aSMauro Carvalho Chehab /* GPIO stuff moved to __saa7134_ir_start() */ 659b285192aSMauro Carvalho Chehab break; 660b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_A16D: 661b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_AVERMEDIA_A16D; 662b285192aSMauro Carvalho Chehab mask_keycode = 0x02F200; 663b285192aSMauro Carvalho Chehab mask_keydown = 0x000400; 664b285192aSMauro Carvalho Chehab polling = 50; /* ms */ 665b285192aSMauro Carvalho Chehab /* GPIO stuff moved to __saa7134_ir_start() */ 666b285192aSMauro Carvalho Chehab break; 667b285192aSMauro Carvalho Chehab case SAA7134_BOARD_KWORLD_TERMINATOR: 668b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_PIXELVIEW; 669b285192aSMauro Carvalho Chehab mask_keycode = 0x00001f; 670b285192aSMauro Carvalho Chehab mask_keyup = 0x000060; 671b285192aSMauro Carvalho Chehab polling = 50; // ms 672b285192aSMauro Carvalho Chehab break; 673b285192aSMauro Carvalho Chehab case SAA7134_BOARD_MANLI_MTV001: 674b285192aSMauro Carvalho Chehab case SAA7134_BOARD_MANLI_MTV002: 675b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_MANLI; 676b285192aSMauro Carvalho Chehab mask_keycode = 0x001f00; 677b285192aSMauro Carvalho Chehab mask_keyup = 0x004000; 678b285192aSMauro Carvalho Chehab polling = 50; /* ms */ 679b285192aSMauro Carvalho Chehab break; 680b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_409FM: 681b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_401: 682b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_403: 683b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_403FM: 684b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_405: 685b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_405FM: 686b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_407: 687b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_407FM: 688b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_409: 689b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_505FM: 690b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_505RDS_MK5: 691b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_505RDS_MK3: 692b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_507_9FM: 693b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_507RDS_MK3: 694b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_507RDS_MK5: 695b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_MANLI; 696b285192aSMauro Carvalho Chehab mask_keycode = 0x003f00; 697b285192aSMauro Carvalho Chehab mask_keyup = 0x004000; 698b285192aSMauro Carvalho Chehab polling = 50; /* ms */ 699b285192aSMauro Carvalho Chehab break; 700b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: 701b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_BEHOLD_COLUMBUS; 702b285192aSMauro Carvalho Chehab mask_keycode = 0x003f00; 703b285192aSMauro Carvalho Chehab mask_keyup = 0x004000; 704b285192aSMauro Carvalho Chehab polling = 50; // ms 705b285192aSMauro Carvalho Chehab break; 706b285192aSMauro Carvalho Chehab case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS: 707b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_PCTV_SEDNA; 708b285192aSMauro Carvalho Chehab mask_keycode = 0x001f00; 709b285192aSMauro Carvalho Chehab mask_keyup = 0x004000; 710b285192aSMauro Carvalho Chehab polling = 50; // ms 711b285192aSMauro Carvalho Chehab break; 712b285192aSMauro Carvalho Chehab case SAA7134_BOARD_GOTVIEW_7135: 713b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_GOTVIEW7135; 714b285192aSMauro Carvalho Chehab mask_keycode = 0x0003CC; 715b285192aSMauro Carvalho Chehab mask_keydown = 0x000010; 716b285192aSMauro Carvalho Chehab polling = 5; /* ms */ 717b285192aSMauro Carvalho Chehab /* GPIO stuff moved to __saa7134_ir_start() */ 718b285192aSMauro Carvalho Chehab break; 719b285192aSMauro Carvalho Chehab case SAA7134_BOARD_VIDEOMATE_TV_PVR: 720b285192aSMauro Carvalho Chehab case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS: 721b285192aSMauro Carvalho Chehab case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII: 722b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_VIDEOMATE_TV_PVR; 723b285192aSMauro Carvalho Chehab mask_keycode = 0x00003F; 724b285192aSMauro Carvalho Chehab mask_keyup = 0x400000; 725b285192aSMauro Carvalho Chehab polling = 50; // ms 726b285192aSMauro Carvalho Chehab break; 727b285192aSMauro Carvalho Chehab case SAA7134_BOARD_PROTEUS_2309: 728b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_PROTEUS_2309; 729b285192aSMauro Carvalho Chehab mask_keycode = 0x00007F; 730b285192aSMauro Carvalho Chehab mask_keyup = 0x000080; 731b285192aSMauro Carvalho Chehab polling = 50; // ms 732b285192aSMauro Carvalho Chehab break; 733b285192aSMauro Carvalho Chehab case SAA7134_BOARD_VIDEOMATE_DVBT_300: 734b285192aSMauro Carvalho Chehab case SAA7134_BOARD_VIDEOMATE_DVBT_200: 735b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_VIDEOMATE_TV_PVR; 736b285192aSMauro Carvalho Chehab mask_keycode = 0x003F00; 737b285192aSMauro Carvalho Chehab mask_keyup = 0x040000; 738b285192aSMauro Carvalho Chehab break; 739b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYDVBS_LR300: 740b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYDVBT_LR301: 741b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYDVBTDUO: 742b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_FLYDVB; 743b285192aSMauro Carvalho Chehab mask_keycode = 0x0001F00; 744b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; 745b285192aSMauro Carvalho Chehab break; 746b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ASUSTeK_P7131_DUAL: 747b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: 748b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ASUSTeK_P7131_ANALOG: 749b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_ASUS_PC39; 750b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ 751b285192aSMauro Carvalho Chehab mask_keyup = 0x0040000; 752b285192aSMauro Carvalho Chehab mask_keycode = 0xffff; 753b285192aSMauro Carvalho Chehab raw_decode = true; 754b285192aSMauro Carvalho Chehab break; 755b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ASUSTeK_PS3_100: 756b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_ASUS_PS3_100; 757b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; 758b285192aSMauro Carvalho Chehab mask_keyup = 0x0040000; 759b285192aSMauro Carvalho Chehab mask_keycode = 0xffff; 760b285192aSMauro Carvalho Chehab raw_decode = true; 761b285192aSMauro Carvalho Chehab break; 762b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ENCORE_ENLTV: 763b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ENCORE_ENLTV_FM: 764b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_ENCORE_ENLTV; 765b285192aSMauro Carvalho Chehab mask_keycode = 0x00007f; 766b285192aSMauro Carvalho Chehab mask_keyup = 0x040000; 767b285192aSMauro Carvalho Chehab polling = 50; // ms 768b285192aSMauro Carvalho Chehab break; 769b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ENCORE_ENLTV_FM53: 770b285192aSMauro Carvalho Chehab case SAA7134_BOARD_ENCORE_ENLTV_FM3: 771b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_ENCORE_ENLTV_FM53; 772b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ 773b285192aSMauro Carvalho Chehab mask_keyup = 0x0040000; 774b285192aSMauro Carvalho Chehab mask_keycode = 0xffff; 775b285192aSMauro Carvalho Chehab raw_decode = true; 776b285192aSMauro Carvalho Chehab break; 777b285192aSMauro Carvalho Chehab case SAA7134_BOARD_10MOONSTVMASTER3: 778b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_ENCORE_ENLTV; 779b285192aSMauro Carvalho Chehab mask_keycode = 0x5f80000; 780b285192aSMauro Carvalho Chehab mask_keyup = 0x8000000; 781b285192aSMauro Carvalho Chehab polling = 50; //ms 782b285192aSMauro Carvalho Chehab break; 783b285192aSMauro Carvalho Chehab case SAA7134_BOARD_GENIUS_TVGO_A11MCE: 784b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_GENIUS_TVGO_A11MCE; 785b285192aSMauro Carvalho Chehab mask_keycode = 0xff; 786b285192aSMauro Carvalho Chehab mask_keydown = 0xf00000; 787b285192aSMauro Carvalho Chehab polling = 50; /* ms */ 788b285192aSMauro Carvalho Chehab break; 789b285192aSMauro Carvalho Chehab case SAA7134_BOARD_REAL_ANGEL_220: 790b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_REAL_AUDIO_220_32_KEYS; 791b285192aSMauro Carvalho Chehab mask_keycode = 0x3f00; 792b285192aSMauro Carvalho Chehab mask_keyup = 0x4000; 793b285192aSMauro Carvalho Chehab polling = 50; /* ms */ 794b285192aSMauro Carvalho Chehab break; 795b285192aSMauro Carvalho Chehab case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG: 796b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_KWORLD_PLUS_TV_ANALOG; 797b285192aSMauro Carvalho Chehab mask_keycode = 0x7f; 798b285192aSMauro Carvalho Chehab polling = 40; /* ms */ 799b285192aSMauro Carvalho Chehab break; 800b285192aSMauro Carvalho Chehab case SAA7134_BOARD_VIDEOMATE_S350: 801b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_VIDEOMATE_S350; 802b285192aSMauro Carvalho Chehab mask_keycode = 0x003f00; 803b285192aSMauro Carvalho Chehab mask_keydown = 0x040000; 804b285192aSMauro Carvalho Chehab break; 805b285192aSMauro Carvalho Chehab case SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S: 806b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_WINFAST; 807b285192aSMauro Carvalho Chehab mask_keycode = 0x5f00; 808b285192aSMauro Carvalho Chehab mask_keyup = 0x020000; 809b285192aSMauro Carvalho Chehab polling = 50; /* ms */ 810b285192aSMauro Carvalho Chehab break; 811b285192aSMauro Carvalho Chehab case SAA7134_BOARD_VIDEOMATE_M1F: 812b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_VIDEOMATE_K100; 813b285192aSMauro Carvalho Chehab mask_keycode = 0x0ff00; 814b285192aSMauro Carvalho Chehab mask_keyup = 0x040000; 815b285192aSMauro Carvalho Chehab break; 816b285192aSMauro Carvalho Chehab case SAA7134_BOARD_HAUPPAUGE_HVR1150: 817b285192aSMauro Carvalho Chehab case SAA7134_BOARD_HAUPPAUGE_HVR1120: 818b285192aSMauro Carvalho Chehab ir_codes = RC_MAP_HAUPPAUGE; 819b285192aSMauro Carvalho Chehab mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ 820b285192aSMauro Carvalho Chehab mask_keyup = 0x0040000; 821b285192aSMauro Carvalho Chehab mask_keycode = 0xffff; 822b285192aSMauro Carvalho Chehab raw_decode = true; 823b285192aSMauro Carvalho Chehab break; 82463ab664cSDarek Zielski case SAA7134_BOARD_LEADTEK_WINFAST_TV2100_FM: 82563ab664cSDarek Zielski ir_codes = RC_MAP_LEADTEK_Y04G0051; 82663ab664cSDarek Zielski mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ 82763ab664cSDarek Zielski mask_keyup = 0x0040000; 82863ab664cSDarek Zielski mask_keycode = 0xffff; 82963ab664cSDarek Zielski raw_decode = true; 83063ab664cSDarek Zielski break; 831b285192aSMauro Carvalho Chehab } 832b285192aSMauro Carvalho Chehab if (NULL == ir_codes) { 8332bb3e2eeSMauro Carvalho Chehab pr_err("Oops: IR config error [card=%d]\n", dev->board); 834b285192aSMauro Carvalho Chehab return -ENODEV; 835b285192aSMauro Carvalho Chehab } 836b285192aSMauro Carvalho Chehab 837b285192aSMauro Carvalho Chehab ir = kzalloc(sizeof(*ir), GFP_KERNEL); 8380f7499fdSAndi Shyti rc = rc_allocate_device(RC_DRIVER_SCANCODE); 839b285192aSMauro Carvalho Chehab if (!ir || !rc) { 840b285192aSMauro Carvalho Chehab err = -ENOMEM; 841b285192aSMauro Carvalho Chehab goto err_out_free; 842b285192aSMauro Carvalho Chehab } 843b285192aSMauro Carvalho Chehab 844b285192aSMauro Carvalho Chehab ir->dev = rc; 845b285192aSMauro Carvalho Chehab dev->remote = ir; 846b285192aSMauro Carvalho Chehab 847b285192aSMauro Carvalho Chehab /* init hardware-specific stuff */ 848b285192aSMauro Carvalho Chehab ir->mask_keycode = mask_keycode; 849b285192aSMauro Carvalho Chehab ir->mask_keydown = mask_keydown; 850b285192aSMauro Carvalho Chehab ir->mask_keyup = mask_keyup; 851b285192aSMauro Carvalho Chehab ir->polling = polling; 852b285192aSMauro Carvalho Chehab ir->raw_decode = raw_decode; 853b285192aSMauro Carvalho Chehab 854b285192aSMauro Carvalho Chehab /* init input device */ 855b285192aSMauro Carvalho Chehab snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)", 856b285192aSMauro Carvalho Chehab saa7134_boards[dev->board].name); 857b285192aSMauro Carvalho Chehab snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", 858b285192aSMauro Carvalho Chehab pci_name(dev->pci)); 859b285192aSMauro Carvalho Chehab 860b285192aSMauro Carvalho Chehab rc->priv = dev; 861b285192aSMauro Carvalho Chehab rc->open = saa7134_ir_open; 862b285192aSMauro Carvalho Chehab rc->close = saa7134_ir_close; 86312c3b9b9SSean Young if (raw_decode) { 864b285192aSMauro Carvalho Chehab rc->driver_type = RC_DRIVER_IR_RAW; 8656d741bfeSSean Young rc->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER; 86612c3b9b9SSean Young } 867b285192aSMauro Carvalho Chehab 868518f4b26SSean Young rc->device_name = ir->name; 869b285192aSMauro Carvalho Chehab rc->input_phys = ir->phys; 870b285192aSMauro Carvalho Chehab rc->input_id.bustype = BUS_PCI; 871b285192aSMauro Carvalho Chehab rc->input_id.version = 1; 872b285192aSMauro Carvalho Chehab if (dev->pci->subsystem_vendor) { 873b285192aSMauro Carvalho Chehab rc->input_id.vendor = dev->pci->subsystem_vendor; 874b285192aSMauro Carvalho Chehab rc->input_id.product = dev->pci->subsystem_device; 875b285192aSMauro Carvalho Chehab } else { 876b285192aSMauro Carvalho Chehab rc->input_id.vendor = dev->pci->vendor; 877b285192aSMauro Carvalho Chehab rc->input_id.product = dev->pci->device; 878b285192aSMauro Carvalho Chehab } 879b285192aSMauro Carvalho Chehab rc->dev.parent = &dev->pci->dev; 880b285192aSMauro Carvalho Chehab rc->map_name = ir_codes; 881b285192aSMauro Carvalho Chehab rc->driver_name = MODULE_NAME; 88248b2de19SSean Young rc->min_timeout = 1; 88348b2de19SSean Young rc->timeout = IR_DEFAULT_TIMEOUT; 88448b2de19SSean Young rc->max_timeout = 10 * IR_DEFAULT_TIMEOUT; 885b285192aSMauro Carvalho Chehab 886b285192aSMauro Carvalho Chehab err = rc_register_device(rc); 887b285192aSMauro Carvalho Chehab if (err) 888b285192aSMauro Carvalho Chehab goto err_out_free; 889b285192aSMauro Carvalho Chehab 890b285192aSMauro Carvalho Chehab return 0; 891b285192aSMauro Carvalho Chehab 892b285192aSMauro Carvalho Chehab err_out_free: 893b285192aSMauro Carvalho Chehab rc_free_device(rc); 894b285192aSMauro Carvalho Chehab dev->remote = NULL; 895b285192aSMauro Carvalho Chehab kfree(ir); 896b285192aSMauro Carvalho Chehab return err; 897b285192aSMauro Carvalho Chehab } 898b285192aSMauro Carvalho Chehab 899b285192aSMauro Carvalho Chehab void saa7134_input_fini(struct saa7134_dev *dev) 900b285192aSMauro Carvalho Chehab { 901b285192aSMauro Carvalho Chehab if (NULL == dev->remote) 902b285192aSMauro Carvalho Chehab return; 903b285192aSMauro Carvalho Chehab 904b285192aSMauro Carvalho Chehab saa7134_ir_stop(dev); 905b285192aSMauro Carvalho Chehab rc_unregister_device(dev->remote->dev); 906b285192aSMauro Carvalho Chehab kfree(dev->remote); 907b285192aSMauro Carvalho Chehab dev->remote = NULL; 908b285192aSMauro Carvalho Chehab } 909b285192aSMauro Carvalho Chehab 910b285192aSMauro Carvalho Chehab void saa7134_probe_i2c_ir(struct saa7134_dev *dev) 911b285192aSMauro Carvalho Chehab { 912b285192aSMauro Carvalho Chehab struct i2c_board_info info; 913b285192aSMauro Carvalho Chehab struct i2c_msg msg_msi = { 914b285192aSMauro Carvalho Chehab .addr = 0x50, 915b285192aSMauro Carvalho Chehab .flags = I2C_M_RD, 916b285192aSMauro Carvalho Chehab .len = 0, 917b285192aSMauro Carvalho Chehab .buf = NULL, 918b285192aSMauro Carvalho Chehab }; 919b285192aSMauro Carvalho Chehab int rc; 920b285192aSMauro Carvalho Chehab 921b285192aSMauro Carvalho Chehab if (disable_ir) { 9226be5b1a1SMauro Carvalho Chehab input_dbg("IR has been disabled, not probing for i2c remote\n"); 923b285192aSMauro Carvalho Chehab return; 924b285192aSMauro Carvalho Chehab } 925b285192aSMauro Carvalho Chehab 926b285192aSMauro Carvalho Chehab memset(&info, 0, sizeof(struct i2c_board_info)); 927b285192aSMauro Carvalho Chehab memset(&dev->init_data, 0, sizeof(dev->init_data)); 928b285192aSMauro Carvalho Chehab strlcpy(info.type, "ir_video", I2C_NAME_SIZE); 929b285192aSMauro Carvalho Chehab 930b285192aSMauro Carvalho Chehab switch (dev->board) { 931b285192aSMauro Carvalho Chehab case SAA7134_BOARD_PINNACLE_PCTV_110i: 932b285192aSMauro Carvalho Chehab case SAA7134_BOARD_PINNACLE_PCTV_310i: 933b285192aSMauro Carvalho Chehab dev->init_data.name = "Pinnacle PCTV"; 934b285192aSMauro Carvalho Chehab if (pinnacle_remote == 0) { 935b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_pinnacle_color; 936b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_PINNACLE_COLOR; 937b285192aSMauro Carvalho Chehab info.addr = 0x47; 938b285192aSMauro Carvalho Chehab } else { 939b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_pinnacle_grey; 940b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_PINNACLE_GREY; 941b285192aSMauro Carvalho Chehab info.addr = 0x47; 942b285192aSMauro Carvalho Chehab } 943b285192aSMauro Carvalho Chehab break; 944b285192aSMauro Carvalho Chehab case SAA7134_BOARD_UPMOST_PURPLE_TV: 945b285192aSMauro Carvalho Chehab dev->init_data.name = "Purple TV"; 946b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_purpletv; 947b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_PURPLETV; 948b285192aSMauro Carvalho Chehab info.addr = 0x7a; 949b285192aSMauro Carvalho Chehab break; 950b285192aSMauro Carvalho Chehab case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS: 951b285192aSMauro Carvalho Chehab dev->init_data.name = "MSI TV@nywhere Plus"; 952b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_msi_tvanywhere_plus; 953b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_MSI_TVANYWHERE_PLUS; 954b285192aSMauro Carvalho Chehab /* 955b285192aSMauro Carvalho Chehab * MSI TV@nyware Plus requires more frequent polling 956b285192aSMauro Carvalho Chehab * otherwise it will miss some keypresses 957b285192aSMauro Carvalho Chehab */ 958b285192aSMauro Carvalho Chehab dev->init_data.polling_interval = 50; 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); 9656be5b1a1SMauro Carvalho Chehab input_dbg("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; 9699c91738dSGEORGE case SAA7134_BOARD_SNAZIO_TVPVR_PRO: 9709c91738dSGEORGE dev->init_data.name = "SnaZio* TVPVR PRO"; 9719c91738dSGEORGE dev->init_data.get_key = get_key_msi_tvanywhere_plus; 9729c91738dSGEORGE dev->init_data.ir_codes = RC_MAP_MSI_TVANYWHERE_PLUS; 9739c91738dSGEORGE /* 9749c91738dSGEORGE * MSI TV@nyware Plus requires more frequent polling 9759c91738dSGEORGE * otherwise it will miss some keypresses 9769c91738dSGEORGE */ 9779c91738dSGEORGE dev->init_data.polling_interval = 50; 9789c91738dSGEORGE info.addr = 0x30; 9799c91738dSGEORGE /* 9809c91738dSGEORGE * MSI TV@nywhere Plus controller doesn't seem to 9819c91738dSGEORGE * respond to probes unless we read something from 9829c91738dSGEORGE * an existing device. Weird... 9839c91738dSGEORGE * REVISIT: might no longer be needed 9849c91738dSGEORGE */ 9859c91738dSGEORGE rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1); 9869c91738dSGEORGE input_dbg("probe 0x%02x @ %s: %s\n", 9879c91738dSGEORGE msg_msi.addr, dev->i2c_adap.name, 9889c91738dSGEORGE (rc == 1) ? "yes" : "no"); 9899c91738dSGEORGE break; 990b285192aSMauro Carvalho Chehab case SAA7134_BOARD_KWORLD_PC150U: 991b285192aSMauro Carvalho Chehab /* copied and modified from MSI TV@nywhere Plus */ 992b285192aSMauro Carvalho Chehab dev->init_data.name = "Kworld PC150-U"; 993b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_kworld_pc150u; 994b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_KWORLD_PC150U; 995b285192aSMauro Carvalho Chehab info.addr = 0x30; 996b285192aSMauro Carvalho Chehab /* MSI TV@nywhere Plus controller doesn't seem to 997b285192aSMauro Carvalho Chehab respond to probes unless we read something from 998b285192aSMauro Carvalho Chehab an existing device. Weird... 999b285192aSMauro Carvalho Chehab REVISIT: might no longer be needed */ 1000b285192aSMauro Carvalho Chehab rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1); 10016be5b1a1SMauro Carvalho Chehab input_dbg("probe 0x%02x @ %s: %s\n", 1002b285192aSMauro Carvalho Chehab msg_msi.addr, dev->i2c_adap.name, 1003b285192aSMauro Carvalho Chehab (1 == rc) ? "yes" : "no"); 1004b285192aSMauro Carvalho Chehab break; 1005b285192aSMauro Carvalho Chehab case SAA7134_BOARD_HAUPPAUGE_HVR1110: 1006b285192aSMauro Carvalho Chehab dev->init_data.name = "HVR 1110"; 1007b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_hvr1110; 1008b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_HAUPPAUGE; 1009b285192aSMauro Carvalho Chehab info.addr = 0x71; 1010b285192aSMauro Carvalho Chehab break; 1011b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_607FM_MK3: 1012b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_607FM_MK5: 1013b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_609FM_MK3: 1014b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_609FM_MK5: 1015b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_607RDS_MK3: 1016b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_607RDS_MK5: 1017b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_609RDS_MK3: 1018b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_609RDS_MK5: 1019b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_M6: 1020b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_M63: 1021b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_M6_EXTRA: 1022b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_H6: 1023b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_X7: 1024b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_H7: 1025b285192aSMauro Carvalho Chehab case SAA7134_BOARD_BEHOLD_A7: 1026b285192aSMauro Carvalho Chehab dev->init_data.name = "BeholdTV"; 1027b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_beholdm6xx; 1028b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_BEHOLD; 10296d741bfeSSean Young dev->init_data.type = RC_PROTO_BIT_NECX; 1030b285192aSMauro Carvalho Chehab info.addr = 0x2d; 1031b285192aSMauro Carvalho Chehab break; 1032b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_CARDBUS_501: 1033b285192aSMauro Carvalho Chehab case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: 1034b285192aSMauro Carvalho Chehab info.addr = 0x40; 1035b285192aSMauro Carvalho Chehab break; 103634fe2784SOndrej Zary case SAA7134_BOARD_AVERMEDIA_A706: 103734fe2784SOndrej Zary info.addr = 0x41; 103834fe2784SOndrej Zary break; 1039b285192aSMauro Carvalho Chehab case SAA7134_BOARD_FLYDVB_TRIO: 1040b285192aSMauro Carvalho Chehab dev->init_data.name = "FlyDVB Trio"; 1041b285192aSMauro Carvalho Chehab dev->init_data.get_key = get_key_flydvb_trio; 1042b285192aSMauro Carvalho Chehab dev->init_data.ir_codes = RC_MAP_FLYDVB; 1043b285192aSMauro Carvalho Chehab info.addr = 0x0b; 1044b285192aSMauro Carvalho Chehab break; 1045b285192aSMauro Carvalho Chehab default: 10466be5b1a1SMauro Carvalho Chehab input_dbg("No I2C IR support for board %x\n", dev->board); 1047b285192aSMauro Carvalho Chehab return; 1048b285192aSMauro Carvalho Chehab } 1049b285192aSMauro Carvalho Chehab 1050b285192aSMauro Carvalho Chehab if (dev->init_data.name) 1051b285192aSMauro Carvalho Chehab info.platform_data = &dev->init_data; 1052b285192aSMauro Carvalho Chehab i2c_new_device(&dev->i2c_adap, &info); 1053b285192aSMauro Carvalho Chehab } 1054b285192aSMauro Carvalho Chehab 1055b285192aSMauro Carvalho Chehab static int saa7134_raw_decode_irq(struct saa7134_dev *dev) 1056b285192aSMauro Carvalho Chehab { 1057b285192aSMauro Carvalho Chehab struct saa7134_card_ir *ir = dev->remote; 1058b285192aSMauro Carvalho Chehab int space; 1059b285192aSMauro Carvalho Chehab 1060b285192aSMauro Carvalho Chehab /* Generate initial event */ 1061b285192aSMauro Carvalho Chehab saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 1062b285192aSMauro Carvalho Chehab saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 1063b285192aSMauro Carvalho Chehab space = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown; 106486fe1ac0SSean Young ir_raw_event_store_edge(dev->remote->dev, !space); 1065b285192aSMauro Carvalho Chehab 1066b285192aSMauro Carvalho Chehab return 1; 1067b285192aSMauro Carvalho Chehab } 1068