3 * handle saa7134 IR remotes via linux kernel input layer.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <linux/module.h>
22 #include <linux/moduleparam.h>
23 #include <linux/init.h>
24 #include <linux/delay.h>
25 #include <linux/sched.h>
26 #include <linux/interrupt.h>
27 #include <linux/input.h>
29 #include "saa7134-reg.h"
32 static unsigned int disable_ir = 0;
33 module_param(disable_ir, int, 0444);
34 MODULE_PARM_DESC(disable_ir,"disable infrared remote support");
36 static unsigned int ir_debug = 0;
37 module_param(ir_debug, int, 0644);
38 MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]");
40 #define dprintk(fmt, arg...) if (ir_debug) \
41 printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg)
42 #define i2cdprintk(fmt, arg...) if (ir_debug) \
43 printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg)
45 /* ---------------------------------------------------------------------- */
47 static IR_KEYTAB_TYPE flyvideo_codes[IR_KEYTAB_SIZE] = {
59 [ 14 ] = KEY_MODE, // Air/Cable
60 [ 17 ] = KEY_VIDEO, // Video
61 [ 21 ] = KEY_AUDIO, // Audio
62 [ 0 ] = KEY_POWER, // Power
63 [ 24 ] = KEY_TUNER, // AV Source
64 [ 2 ] = KEY_ZOOM, // Fullscreen
65 [ 26 ] = KEY_LANGUAGE, // Stereo
66 [ 27 ] = KEY_MUTE, // Mute
67 [ 20 ] = KEY_VOLUMEUP, // Volume +
68 [ 23 ] = KEY_VOLUMEDOWN, // Volume -
69 [ 18 ] = KEY_CHANNELUP, // Channel +
70 [ 19 ] = KEY_CHANNELDOWN, // Channel -
71 [ 6 ] = KEY_AGAIN, // Recall
72 [ 16 ] = KEY_ENTER, // Enter
76 static IR_KEYTAB_TYPE cinergy_codes[IR_KEYTAB_SIZE] = {
89 [ 0x0b ] = KEY_PROG1, // app
90 [ 0x0c ] = KEY_ZOOM, // zoom/fullscreen
91 [ 0x0d ] = KEY_CHANNELUP, // channel
92 [ 0x0e ] = KEY_CHANNELDOWN, // channel-
93 [ 0x0f ] = KEY_VOLUMEUP,
94 [ 0x10 ] = KEY_VOLUMEDOWN,
95 [ 0x11 ] = KEY_TUNER, // AV
96 [ 0x12 ] = KEY_NUMLOCK, // -/--
97 [ 0x13 ] = KEY_AUDIO, // audio
102 [ 0x18 ] = KEY_RIGHT,
104 [ 0x1a ] = BTN_RIGHT,
105 [ 0x1b ] = KEY_WWW, // text
106 [ 0x1c ] = KEY_REWIND,
107 [ 0x1d ] = KEY_FORWARD,
108 [ 0x1e ] = KEY_RECORD,
110 [ 0x20 ] = KEY_PREVIOUSSONG,
111 [ 0x21 ] = KEY_NEXTSONG,
112 [ 0x22 ] = KEY_PAUSE,
116 /* Alfons Geser <a.geser@cox.net>
117 * updates from Job D. R. Borges <jobdrb@ig.com.br> */
118 static IR_KEYTAB_TYPE eztv_codes[IR_KEYTAB_SIZE] = {
120 [ 1 ] = KEY_TV, // DVR
121 [ 21 ] = KEY_DVD, // DVD
122 [ 23 ] = KEY_AUDIO, // music
123 // DVR mode / DVD mode / music mode
125 [ 27 ] = KEY_MUTE, // mute
126 [ 2 ] = KEY_LANGUAGE, // MTS/SAP / audio / autoseek
127 [ 30 ] = KEY_SUBTITLE, // closed captioning / subtitle / seek
128 [ 22 ] = KEY_ZOOM, // full screen
129 [ 28 ] = KEY_VIDEO, // video source / eject / delall
130 [ 29 ] = KEY_RESTART, // playback / angle / del
131 [ 47 ] = KEY_SEARCH, // scan / menu / playlist
132 [ 48 ] = KEY_CHANNEL, // CH surfing / bookmark / memo
134 [ 49 ] = KEY_HELP, // help
135 [ 50 ] = KEY_MODE, // num/memo
136 [ 51 ] = KEY_ESC, // cancel
138 [ 12 ] = KEY_UP, // up
139 [ 16 ] = KEY_DOWN, // down
140 [ 8 ] = KEY_LEFT, // left
141 [ 4 ] = KEY_RIGHT, // right
142 [ 3 ] = KEY_SELECT, // select
144 [ 31 ] = KEY_REWIND, // rewind
145 [ 32 ] = KEY_PLAYPAUSE, // play/pause
146 [ 41 ] = KEY_FORWARD, // forward
147 [ 20 ] = KEY_AGAIN, // repeat
148 [ 43 ] = KEY_RECORD, // recording
149 [ 44 ] = KEY_STOP, // stop
150 [ 45 ] = KEY_PLAY, // play
151 [ 46 ] = KEY_SHUFFLE, // snapshot / shuffle
164 [ 42 ] = KEY_VOLUMEUP,
165 [ 17 ] = KEY_VOLUMEDOWN,
166 [ 24 ] = KEY_CHANNELUP, // CH.tracking up
167 [ 25 ] = KEY_CHANNELDOWN, // CH.tracking down
169 [ 19 ] = KEY_KPENTER, // enter
170 [ 33 ] = KEY_KPDOT, // . (decimal dot)
173 static IR_KEYTAB_TYPE avacssmart_codes[IR_KEYTAB_SIZE] = {
174 [ 30 ] = KEY_POWER, // power
175 [ 28 ] = KEY_SEARCH, // scan
176 [ 7 ] = KEY_SELECT, // source
178 [ 22 ] = KEY_VOLUMEUP,
179 [ 20 ] = KEY_VOLUMEDOWN,
180 [ 31 ] = KEY_CHANNELUP,
181 [ 23 ] = KEY_CHANNELDOWN,
196 [ 3 ] = KEY_TUNER, // tv/fm
197 [ 4 ] = KEY_REWIND, // fm tuning left or function left
198 [ 12 ] = KEY_FORWARD, // fm tuning right or function right
205 [ 14 ] = KEY_MENU, // function
206 [ 19 ] = KEY_AGAIN, // recall
207 [ 29 ] = KEY_RESTART, // reset
208 [ 26 ] = KEY_SHUFFLE, // snapshot/shuffle
211 [ 13 ] = KEY_F21, // mts
212 [ 15 ] = KEY_F22, // min
215 /* Alex Hermann <gaaf@gmx.net> */
216 static IR_KEYTAB_TYPE md2819_codes[IR_KEYTAB_SIZE] = {
228 [ 32 ] = KEY_TV, // TV/FM
229 [ 16 ] = KEY_CD, // CD
230 [ 48 ] = KEY_TEXT, // TELETEXT
231 [ 0 ] = KEY_POWER, // POWER
233 [ 8 ] = KEY_VIDEO, // VIDEO
234 [ 4 ] = KEY_AUDIO, // AUDIO
235 [ 12 ] = KEY_ZOOM, // FULL SCREEN
237 [ 18 ] = KEY_SUBTITLE, // DISPLAY - ???
238 [ 50 ] = KEY_REWIND, // LOOP - ???
239 [ 2 ] = KEY_PRINT, // PREVIEW - ???
241 [ 42 ] = KEY_SEARCH, // AUTOSCAN
242 [ 26 ] = KEY_SLEEP, // FREEZE - ???
243 [ 58 ] = KEY_SHUFFLE, // SNAPSHOT - ???
244 [ 10 ] = KEY_MUTE, // MUTE
246 [ 38 ] = KEY_RECORD, // RECORD
247 [ 22 ] = KEY_PAUSE, // PAUSE
248 [ 54 ] = KEY_STOP, // STOP
249 [ 6 ] = KEY_PLAY, // PLAY
251 [ 46 ] = KEY_RED, // <RED>
252 [ 33 ] = KEY_GREEN, // <GREEN>
253 [ 14 ] = KEY_YELLOW, // <YELLOW>
254 [ 1 ] = KEY_BLUE, // <BLUE>
256 [ 30 ] = KEY_VOLUMEDOWN, // VOLUME-
257 [ 62 ] = KEY_VOLUMEUP, // VOLUME+
258 [ 17 ] = KEY_CHANNELDOWN, // CHANNEL/PAGE-
259 [ 49 ] = KEY_CHANNELUP // CHANNEL/PAGE+
262 static IR_KEYTAB_TYPE videomate_tv_pvr_codes[IR_KEYTAB_SIZE] = {
271 [ 8 ] = KEY_PLAYPAUSE,
272 [ 15 ] = KEY_FORWARD,
274 [ 2 ] = KEY_PREVIOUS,
287 [ 34 ] = KEY_CHANNEL,
289 [ 18 ] = KEY_VOLUMEUP,
290 [ 21 ] = KEY_VOLUMEDOWN,
291 [ 16 ] = KEY_CHANNELUP,
292 [ 19 ] = KEY_CHANNELDOWN,
307 [ 32 ] = KEY_LANGUAGE,
311 /* Michael Tokarev <mjt@tls.msk.ru>
312 http://www.corpit.ru/mjt/beholdTV/remote_control.jpg
313 keytable is used by MANLI MTV00[12] and BeholdTV 40[13] at
314 least, and probably other cards too.
315 The "ascii-art picture" below (in comments, first row
316 is the keycode in hex, and subsequent row(s) shows
317 the button labels (several variants when appropriate)
318 helps to descide which keycodes to assign to the buttons.
320 static IR_KEYTAB_TYPE manli_codes[IR_KEYTAB_SIZE] = {
326 [ 0x1c ] = KEY_RADIO, /*XXX*/
327 [ 0x12 ] = KEY_POWER,
352 [ 0x0a ] = KEY_AGAIN, /*XXX KEY_REWIND? */
354 [ 0x17 ] = KEY_DIGITS, /*XXX*/
371 [ 0x0b ] = KEY_UP, /*XXX KEY_SCROLLUP? */
372 [ 0x18 ] = KEY_LEFT, /*XXX KEY_BACK? */
373 [ 0x16 ] = KEY_OK, /*XXX KEY_SELECT? KEY_ENTER? */
374 [ 0x0c ] = KEY_RIGHT, /*XXX KEY_FORWARD? */
375 [ 0x15 ] = KEY_DOWN, /*XXX KEY_SCROLLDOWN? */
381 [ 0x11 ] = KEY_TV, /*XXX*/
382 [ 0x0d ] = KEY_MODE, /*XXX there's no KEY_STEREO */
391 [ 0x0f ] = KEY_AUDIO,
392 [ 0x1b ] = KEY_VOLUMEUP,
393 [ 0x1a ] = KEY_CHANNELUP,
394 [ 0x0e ] = KEY_SLEEP, /*XXX maybe KEY_PAUSE */
395 [ 0x1f ] = KEY_VOLUMEDOWN,
396 [ 0x1e ] = KEY_CHANNELDOWN,
402 [ 0x19 ] = KEY_RECORD, /*XXX*/
408 /* Mike Baikov <mike@baikov.com> */
409 static IR_KEYTAB_TYPE gotview7135_codes[IR_KEYTAB_SIZE] = {
423 [ 115] = KEY_AGAIN, /* LOOP */
425 [ 97 ] = KEY_PRINT, /* PREVIEW */
427 [ 32 ] = KEY_CHANNELUP,
428 [ 64 ] = KEY_CHANNELDOWN,
429 [ 24 ] = KEY_VOLUMEDOWN,
430 [ 80 ] = KEY_VOLUMEUP,
433 [ 123] = KEY_SHUFFLE, /* SNAPSHOT */
439 [ 25 ] = KEY_FORWARD,
442 [ 82 ] = KEY_F21, /* LIVE TIMESHIFT */
443 [ 26 ] = KEY_F22, /* MIN TIMESHIFT */
444 [ 58 ] = KEY_F23, /* TIMESHIFT */
445 [ 112] = KEY_F24, /* NORMAL TIMESHIFT */
448 static IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = {
451 [ 0x10 ] = KEY_BACKSPACE, /* Recall */
463 [ 0x12 ] = KEY_KPDOT, /* 100+ */
465 [ 0x7 ] = KEY_VOLUMEUP,
466 [ 0xb ] = KEY_VOLUMEDOWN,
467 [ 0x1a ] = KEY_KPPLUS,
468 [ 0x18 ] = KEY_KPMINUS,
471 [ 0xf ] = KEY_CHANNELUP,
472 [ 0x13 ] = KEY_CHANNELDOWN,
475 [ 0x1b ] = KEY_VIDEO, /* Video source */
476 [ 0x49 ] = KEY_LANGUAGE, /* MTS Select */
477 [ 0x19 ] = KEY_SEARCH, /* Auto Scan */
479 [ 0x4b ] = KEY_RECORD,
481 [ 0x45 ] = KEY_PAUSE, /* Pause */
483 [ 0x40 ] = KEY_FORWARD, /* Forward ? */
484 [ 0x42 ] = KEY_REWIND, /* Backward ? */
488 /* Mapping for the 28 key remote control as seen at
489 http://www.sednacomputer.com/photo/cardbus-tv.jpg
490 Pavel Mihaylov <bin@bash.info> */
491 static IR_KEYTAB_TYPE pctv_sedna_codes[IR_KEYTAB_SIZE] = {
503 [ 0x0a ] = KEY_AGAIN, /* Recall */
504 [ 0x0b ] = KEY_CHANNELUP,
505 [ 0x0c ] = KEY_VOLUMEUP,
506 [ 0x0d ] = KEY_MODE, /* Stereo */
508 [ 0x0f ] = KEY_PREVIOUSSONG,
510 [ 0x11 ] = KEY_TUNER, /* Source */
511 [ 0x12 ] = KEY_POWER,
513 [ 0x15 ] = KEY_CHANNELDOWN,
514 [ 0x18 ] = KEY_VOLUMEDOWN,
515 [ 0x19 ] = KEY_SHUFFLE, /* Snapshot */
516 [ 0x1a ] = KEY_NEXTSONG,
517 [ 0x1b ] = KEY_TEXT, /* Time Shift */
518 [ 0x1c ] = KEY_RADIO, /* FM Radio */
519 [ 0x1d ] = KEY_RECORD,
520 [ 0x1e ] = KEY_PAUSE,
524 /* -------------------- GPIO generic keycode builder -------------------- */
526 static int build_key(struct saa7134_dev *dev)
528 struct saa7134_ir *ir = dev->remote;
531 /* rising SAA7134_GPIO_GPRESCAN reads the status */
532 saa_clearb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN);
533 saa_setb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN);
535 gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2);
537 if (ir->last_gpio == gpio)
539 ir->last_gpio = gpio;
542 data = ir_extract_bits(gpio, ir->mask_keycode);
543 dprintk("build_key gpio=0x%x mask=0x%x data=%d\n",
544 gpio, ir->mask_keycode, data);
547 if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) ||
548 (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) {
549 ir_input_keydown(ir->dev, &ir->ir, data, data);
551 ir_input_nokey(ir->dev, &ir->ir);
554 else { /* IRQ driven mode - handle key press and release in one go */
555 if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) ||
556 (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) {
557 ir_input_keydown(ir->dev, &ir->ir, data, data);
558 ir_input_nokey(ir->dev, &ir->ir);
565 /* --------------------- Chip specific I2C key builders ----------------- */
567 static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
572 if (1 != i2c_master_recv(&ir->c,&b,1)) {
573 i2cdprintk("read error\n");
577 /* no button press */
590 void saa7134_input_irq(struct saa7134_dev *dev)
592 struct saa7134_ir *ir = dev->remote;
598 static void saa7134_input_timer(unsigned long data)
600 struct saa7134_dev *dev = (struct saa7134_dev*)data;
601 struct saa7134_ir *ir = dev->remote;
602 unsigned long timeout;
605 timeout = jiffies + (ir->polling * HZ / 1000);
606 mod_timer(&ir->timer, timeout);
609 int saa7134_input_init1(struct saa7134_dev *dev)
611 struct saa7134_ir *ir;
612 struct input_dev *input_dev;
613 IR_KEYTAB_TYPE *ir_codes = NULL;
614 u32 mask_keycode = 0;
615 u32 mask_keydown = 0;
618 int ir_type = IR_TYPE_OTHER;
620 if (dev->has_remote != SAA7134_REMOTE_GPIO)
625 /* detect & configure */
626 switch (dev->board) {
627 case SAA7134_BOARD_FLYVIDEO2000:
628 case SAA7134_BOARD_FLYVIDEO3000:
629 case SAA7134_BOARD_FLYTVPLATINUM_FM:
630 case SAA7134_BOARD_FLYTVPLATINUM_MINI2:
631 ir_codes = flyvideo_codes;
632 mask_keycode = 0xEC00000;
633 mask_keydown = 0x0040000;
635 case SAA7134_BOARD_CINERGY400:
636 case SAA7134_BOARD_CINERGY600:
637 case SAA7134_BOARD_CINERGY600_MK3:
638 ir_codes = cinergy_codes;
639 mask_keycode = 0x00003f;
640 mask_keyup = 0x040000;
642 case SAA7134_BOARD_ECS_TVP3XP:
643 case SAA7134_BOARD_ECS_TVP3XP_4CB5:
644 ir_codes = eztv_codes;
645 mask_keycode = 0x00017c;
646 mask_keyup = 0x000002;
649 case SAA7134_BOARD_KWORLD_XPERT:
650 case SAA7134_BOARD_AVACSSMARTTV:
651 ir_codes = avacssmart_codes;
652 mask_keycode = 0x00001F;
653 mask_keyup = 0x000020;
656 case SAA7134_BOARD_MD2819:
657 case SAA7134_BOARD_KWORLD_VSTREAM_XPERT:
658 case SAA7134_BOARD_AVERMEDIA_305:
659 case SAA7134_BOARD_AVERMEDIA_307:
660 case SAA7134_BOARD_AVERMEDIA_STUDIO_305:
661 case SAA7134_BOARD_AVERMEDIA_STUDIO_307:
662 case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
663 ir_codes = md2819_codes;
664 mask_keycode = 0x0007C8;
665 mask_keydown = 0x000010;
667 /* Set GPIO pin2 to high to enable the IR controller */
668 saa_setb(SAA7134_GPIO_GPMODE0, 0x4);
669 saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4);
671 case SAA7134_BOARD_KWORLD_TERMINATOR:
672 ir_codes = avacssmart_codes;
673 mask_keycode = 0x00001f;
674 mask_keyup = 0x000060;
677 case SAA7134_BOARD_MANLI_MTV001:
678 case SAA7134_BOARD_MANLI_MTV002:
679 case SAA7134_BOARD_BEHOLD_409FM:
680 ir_codes = manli_codes;
681 mask_keycode = 0x001f00;
682 mask_keyup = 0x004000;
685 case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS:
686 ir_codes = pctv_sedna_codes;
687 mask_keycode = 0x001f00;
688 mask_keyup = 0x004000;
691 case SAA7134_BOARD_GOTVIEW_7135:
692 ir_codes = gotview7135_codes;
693 mask_keycode = 0x0003EC;
694 mask_keyup = 0x008000;
695 mask_keydown = 0x000010;
698 case SAA7134_BOARD_VIDEOMATE_TV_PVR:
699 case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS:
700 case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII:
701 ir_codes = videomate_tv_pvr_codes;
702 mask_keycode = 0x00003F;
703 mask_keyup = 0x400000;
706 case SAA7134_BOARD_VIDEOMATE_DVBT_300:
707 case SAA7134_BOARD_VIDEOMATE_DVBT_200:
708 ir_codes = videomate_tv_pvr_codes;
709 mask_keycode = 0x003F00;
710 mask_keyup = 0x040000;
713 if (NULL == ir_codes) {
714 printk("%s: Oops: IR config error [card=%d]\n",
715 dev->name, dev->board);
719 ir = kzalloc(sizeof(*ir), GFP_KERNEL);
720 input_dev = input_allocate_device();
721 if (!ir || !input_dev) {
723 input_free_device(input_dev);
729 /* init hardware-specific stuff */
730 ir->mask_keycode = mask_keycode;
731 ir->mask_keydown = mask_keydown;
732 ir->mask_keyup = mask_keyup;
733 ir->polling = polling;
735 /* init input device */
736 snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)",
737 saa7134_boards[dev->board].name);
738 snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
741 ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
742 input_dev->name = ir->name;
743 input_dev->phys = ir->phys;
744 input_dev->id.bustype = BUS_PCI;
745 input_dev->id.version = 1;
746 if (dev->pci->subsystem_vendor) {
747 input_dev->id.vendor = dev->pci->subsystem_vendor;
748 input_dev->id.product = dev->pci->subsystem_device;
750 input_dev->id.vendor = dev->pci->vendor;
751 input_dev->id.product = dev->pci->device;
753 input_dev->cdev.dev = &dev->pci->dev;
758 init_timer(&ir->timer);
759 ir->timer.function = saa7134_input_timer;
760 ir->timer.data = (unsigned long)dev;
761 ir->timer.expires = jiffies + HZ;
762 add_timer(&ir->timer);
765 input_register_device(ir->dev);
769 void saa7134_input_fini(struct saa7134_dev *dev)
771 if (NULL == dev->remote)
774 if (dev->remote->polling)
775 del_timer_sync(&dev->remote->timer);
776 input_unregister_device(dev->remote->dev);
781 void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir)
784 dprintk("Found supported i2c remote, but IR has been disabled\n");
789 switch (dev->board) {
790 case SAA7134_BOARD_PINNACLE_PCTV_110i:
791 snprintf(ir->c.name, sizeof(ir->c.name), "Pinnacle PCTV");
792 ir->get_key = get_key_pinnacle;
793 ir->ir_codes = ir_codes_pinnacle;
795 case SAA7134_BOARD_UPMOST_PURPLE_TV:
796 snprintf(ir->c.name, sizeof(ir->c.name), "Purple TV");
797 ir->get_key = get_key_purpletv;
798 ir->ir_codes = ir_codes_purpletv;
801 dprintk("Shouldn't get here: Unknown board %x for I2C IR?\n",dev->board);
806 /* ----------------------------------------------------------------------