Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

V4L/DVB (4023): Subject: Pinnacle PCTV grey remote control support

This adds support for the older (?) Pinnacle PCTV remotes (with all buttons
colored in grey). There's no autodetection for the type of remote, though;
saa7134 defaults to the colored one, to use the grey remote the
"pinnacle_remote=1" option must be passed to the saa7134 module

Signed-off-by: Sylvain Pasche <sylvain.pasche@gmail.com>
Signed-off-by: Ricardo Cerqueira <v4l@cerqueira.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>

authored by

Sylvain Pasche and committed by
Mauro Carvalho Chehab
b93eedb6 e48a9c62

+67 -27
+4 -4
drivers/media/common/ir-keymaps.c
··· 618 618 619 619 EXPORT_SYMBOL_GPL(ir_codes_em_terratec); 620 620 621 - IR_KEYTAB_TYPE ir_codes_em_pinnacle_usb[IR_KEYTAB_SIZE] = { 621 + IR_KEYTAB_TYPE ir_codes_pinnacle_grey[IR_KEYTAB_SIZE] = { 622 622 [ 0x3a ] = KEY_0, 623 623 [ 0x31 ] = KEY_1, 624 624 [ 0x32 ] = KEY_2, ··· 670 670 [ 0x27 ] = KEY_RECORD, 671 671 }; 672 672 673 - EXPORT_SYMBOL_GPL(ir_codes_em_pinnacle_usb); 673 + EXPORT_SYMBOL_GPL(ir_codes_pinnacle_grey); 674 674 675 675 IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE] = { 676 676 [ 0x0f ] = KEY_0, ··· 1290 1290 1291 1291 EXPORT_SYMBOL_GPL(ir_codes_winfast); 1292 1292 1293 - IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE] = { 1293 + IR_KEYTAB_TYPE ir_codes_pinnacle_color[IR_KEYTAB_SIZE] = { 1294 1294 [ 0x59 ] = KEY_MUTE, 1295 1295 [ 0x4a ] = KEY_POWER, 1296 1296 ··· 1348 1348 [ 0x0a ] = KEY_BACKSPACE, 1349 1349 }; 1350 1350 1351 - EXPORT_SYMBOL_GPL(ir_codes_pinnacle); 1351 + EXPORT_SYMBOL_GPL(ir_codes_pinnacle_color); 1352 1352 1353 1353 /* Hauppauge: the newer, gray remotes (seems there are multiple 1354 1354 * slightly different versions), shipped with cx88+ivtv cards.
+3 -3
drivers/media/video/em28xx/em28xx-input.c
··· 105 105 return 1; 106 106 } 107 107 108 - static int get_key_pinnacle_usb(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) 108 + static int get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) 109 109 { 110 110 unsigned char buf[3]; 111 111 ··· 148 148 snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM28XX Terratec)"); 149 149 break; 150 150 case (EM2820_BOARD_PINNACLE_USB_2): 151 - ir->ir_codes = ir_codes_em_pinnacle_usb; 152 - ir->get_key = get_key_pinnacle_usb; 151 + ir->ir_codes = ir_codes_pinnacle_grey; 152 + ir->get_key = get_key_pinnacle_usb_grey; 153 153 snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM28XX Pinnacle PCTV)"); 154 154 break; 155 155 case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2):
+45 -15
drivers/media/video/ir-kbd-i2c.c
··· 150 150 return 1; 151 151 } 152 152 153 - /* The new pinnacle PCTV remote (with the colored buttons) 153 + /* Common (grey or coloured) pinnacle PCTV remote handling 154 154 * 155 - * Ricardo Cerqueira <v4l@cerqueira.org> 156 155 */ 157 - 158 - int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) 156 + static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw, 157 + int parity_offset, int marker, int code_modulo) 159 158 { 160 159 unsigned char b[4]; 161 160 unsigned int start = 0,parity = 0,code = 0; ··· 166 167 } 167 168 168 169 for (start = 0; start<4; start++) { 169 - if (b[start] == 0x80) { 170 - code=b[(start+3)%4]; 171 - parity=b[(start+2)%4]; 170 + if (b[start] == marker) { 171 + code=b[(start+parity_offset+1)%4]; 172 + parity=b[(start+parity_offset)%4]; 172 173 } 173 174 } 174 175 ··· 180 181 if (ir->old == parity) 181 182 return 0; 182 183 183 - 184 184 ir->old = parity; 185 185 186 - /* Reduce code value to fit inside IR_KEYTAB_SIZE 187 - * 188 - * this is the only value that results in 42 unique 189 - * codes < 128 190 - */ 186 + /* drop special codes when a key is held down a long time for the grey controller 187 + In this case, the second bit of the code is asserted */ 188 + if (marker == 0xfe && (code & 0x40)) 189 + return 0; 191 190 192 - code %= 0x88; 191 + code %= code_modulo; 193 192 194 193 *ir_raw = code; 195 194 *ir_key = code; ··· 197 200 return 1; 198 201 } 199 202 200 - EXPORT_SYMBOL_GPL(get_key_pinnacle); 203 + /* The grey pinnacle PCTV remote 204 + * 205 + * There are one issue with this remote: 206 + * - I2c packet does not change when the same key is pressed quickly. The workaround 207 + * is to hold down each key for about half a second, so that another code is generated 208 + * in the i2c packet, and the function can distinguish key presses. 209 + * 210 + * Sylvain Pasche <sylvain.pasche@gmail.com> 211 + */ 212 + int get_key_pinnacle_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) 213 + { 214 + 215 + return get_key_pinnacle(ir, ir_key, ir_raw, 1, 0xfe, 0xff); 216 + } 217 + 218 + EXPORT_SYMBOL_GPL(get_key_pinnacle_grey); 219 + 220 + 221 + /* The new pinnacle PCTV remote (with the colored buttons) 222 + * 223 + * Ricardo Cerqueira <v4l@cerqueira.org> 224 + */ 225 + int get_key_pinnacle_color(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) 226 + { 227 + /* code_modulo parameter (0x88) is used to reduce code value to fit inside IR_KEYTAB_SIZE 228 + * 229 + * this is the only value that results in 42 unique 230 + * codes < 128 231 + */ 232 + 233 + return get_key_pinnacle(ir, ir_key, ir_raw, 2, 0x80, 0x88); 234 + } 235 + 236 + EXPORT_SYMBOL_GPL(get_key_pinnacle_color); 201 237 202 238 /* ----------------------------------------------------------------------- */ 203 239
+11 -2
drivers/media/video/saa7134/saa7134-input.c
··· 37 37 module_param(ir_debug, int, 0644); 38 38 MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]"); 39 39 40 + static int pinnacle_remote = 0; 41 + module_param(pinnacle_remote, int, 0644); /* Choose Pinnacle PCTV remote */ 42 + MODULE_PARM_DESC(pinnacle_remote, "Specify Pinnacle PCTV remote: 0=coloured, 1=grey (defaults to 0)"); 43 + 40 44 #define dprintk(fmt, arg...) if (ir_debug) \ 41 45 printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg) 42 46 #define i2cdprintk(fmt, arg...) if (ir_debug) \ ··· 320 316 switch (dev->board) { 321 317 case SAA7134_BOARD_PINNACLE_PCTV_110i: 322 318 snprintf(ir->c.name, sizeof(ir->c.name), "Pinnacle PCTV"); 323 - ir->get_key = get_key_pinnacle; 324 - ir->ir_codes = ir_codes_pinnacle; 319 + if (pinnacle_remote == 0) { 320 + ir->get_key = get_key_pinnacle_color; 321 + ir->ir_codes = ir_codes_pinnacle_color; 322 + } else { 323 + ir->get_key = get_key_pinnacle_grey; 324 + ir->ir_codes = ir_codes_pinnacle_grey; 325 + } 325 326 break; 326 327 case SAA7134_BOARD_UPMOST_PURPLE_TV: 327 328 snprintf(ir->c.name, sizeof(ir->c.name), "Purple TV");
+2 -2
include/media/ir-common.h
··· 73 73 extern IR_KEYTAB_TYPE ir_codes_avertv_303[IR_KEYTAB_SIZE]; 74 74 extern IR_KEYTAB_TYPE ir_codes_dntv_live_dvbt_pro[IR_KEYTAB_SIZE]; 75 75 extern IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE]; 76 - extern IR_KEYTAB_TYPE ir_codes_em_pinnacle_usb[IR_KEYTAB_SIZE]; 76 + extern IR_KEYTAB_TYPE ir_codes_pinnacle_grey[IR_KEYTAB_SIZE]; 77 77 extern IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE]; 78 78 extern IR_KEYTAB_TYPE ir_codes_flydvb[IR_KEYTAB_SIZE]; 79 79 extern IR_KEYTAB_TYPE ir_codes_cinergy[IR_KEYTAB_SIZE]; ··· 87 87 extern IR_KEYTAB_TYPE ir_codes_pv951[IR_KEYTAB_SIZE]; 88 88 extern IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE]; 89 89 extern IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE]; 90 - extern IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE]; 90 + extern IR_KEYTAB_TYPE ir_codes_pinnacle_color[IR_KEYTAB_SIZE]; 91 91 extern IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE]; 92 92 93 93 #endif
+2 -1
include/media/ir-kbd-i2c.h
··· 20 20 int (*get_key)(struct IR_i2c*, u32*, u32*); 21 21 }; 22 22 23 - int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw); 23 + int get_key_pinnacle_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw); 24 + int get_key_pinnacle_color(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw); 24 25 #endif