Merge upstream (approx. 2.6.12-git8) into 'janitor' branch of netdev-2.6.
[linux-2.6] / drivers / media / video / saa7134 / saa7134-input.c
1 /*
2  * $Id: saa7134-input.c,v 1.19 2005/06/07 18:02:26 nsh Exp $
3  *
4  * handle saa7134 IR remotes via linux kernel input layer.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21
22 #include <linux/module.h>
23 #include <linux/moduleparam.h>
24 #include <linux/init.h>
25 #include <linux/delay.h>
26 #include <linux/sched.h>
27 #include <linux/interrupt.h>
28 #include <linux/input.h>
29
30 #include "saa7134-reg.h"
31 #include "saa7134.h"
32
33 static unsigned int disable_ir = 0;
34 module_param(disable_ir, int, 0444);
35 MODULE_PARM_DESC(disable_ir,"disable infrared remote support");
36
37 static unsigned int ir_debug = 0;
38 module_param(ir_debug, int, 0644);
39 MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]");
40
41 #define dprintk(fmt, arg...)    if (ir_debug) \
42         printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg)
43
44 /* ---------------------------------------------------------------------- */
45
46 static IR_KEYTAB_TYPE flyvideo_codes[IR_KEYTAB_SIZE] = {
47         [   15 ] = KEY_KP0,
48         [    3 ] = KEY_KP1,
49         [    4 ] = KEY_KP2,
50         [    5 ] = KEY_KP3,
51         [    7 ] = KEY_KP4,
52         [    8 ] = KEY_KP5,
53         [    9 ] = KEY_KP6,
54         [   11 ] = KEY_KP7,
55         [   12 ] = KEY_KP8,
56         [   13 ] = KEY_KP9,
57
58         [   14 ] = KEY_TUNER,        // Air/Cable
59         [   17 ] = KEY_VIDEO,        // Video
60         [   21 ] = KEY_AUDIO,        // Audio
61         [    0 ] = KEY_POWER,        // Pover
62         [    2 ] = KEY_ZOOM,         // Fullscreen
63         [   27 ] = KEY_MUTE,         // Mute
64         [   20 ] = KEY_VOLUMEUP,
65         [   23 ] = KEY_VOLUMEDOWN,
66         [   18 ] = KEY_CHANNELUP,    // Channel +
67         [   19 ] = KEY_CHANNELDOWN,  // Channel -
68         [    6 ] = KEY_AGAIN,        // Recal
69         [   16 ] = KEY_KPENTER,      // Enter
70
71 #if 1 /* FIXME */
72         [   26 ] = KEY_F22,          // Stereo
73         [   24 ] = KEY_EDIT,         // AV Source
74 #endif
75 };
76
77 static IR_KEYTAB_TYPE cinergy_codes[IR_KEYTAB_SIZE] = {
78         [    0 ] = KEY_KP0,
79         [    1 ] = KEY_KP1,
80         [    2 ] = KEY_KP2,
81         [    3 ] = KEY_KP3,
82         [    4 ] = KEY_KP4,
83         [    5 ] = KEY_KP5,
84         [    6 ] = KEY_KP6,
85         [    7 ] = KEY_KP7,
86         [    8 ] = KEY_KP8,
87         [    9 ] = KEY_KP9,
88
89         [ 0x0a ] = KEY_POWER,
90         [ 0x0b ] = KEY_PROG1,           // app
91         [ 0x0c ] = KEY_ZOOM,            // zoom/fullscreen
92         [ 0x0d ] = KEY_CHANNELUP,       // channel
93         [ 0x0e ] = KEY_CHANNELDOWN,     // channel-
94         [ 0x0f ] = KEY_VOLUMEUP,
95         [ 0x10 ] = KEY_VOLUMEDOWN,
96         [ 0x11 ] = KEY_TUNER,           // AV
97         [ 0x12 ] = KEY_NUMLOCK,         // -/--
98         [ 0x13 ] = KEY_AUDIO,           // audio
99         [ 0x14 ] = KEY_MUTE,
100         [ 0x15 ] = KEY_UP,
101         [ 0x16 ] = KEY_DOWN,
102         [ 0x17 ] = KEY_LEFT,
103         [ 0x18 ] = KEY_RIGHT,
104         [ 0x19 ] = BTN_LEFT,
105         [ 0x1a ] = BTN_RIGHT,
106         [ 0x1b ] = KEY_WWW,             // text
107         [ 0x1c ] = KEY_REWIND,
108         [ 0x1d ] = KEY_FORWARD,
109         [ 0x1e ] = KEY_RECORD,
110         [ 0x1f ] = KEY_PLAY,
111         [ 0x20 ] = KEY_PREVIOUSSONG,
112         [ 0x21 ] = KEY_NEXTSONG,
113         [ 0x22 ] = KEY_PAUSE,
114         [ 0x23 ] = KEY_STOP,
115 };
116
117 /* Alfons Geser <a.geser@cox.net>
118  * updates from Job D. R. Borges <jobdrb@ig.com.br> */
119 static IR_KEYTAB_TYPE eztv_codes[IR_KEYTAB_SIZE] = {
120         [ 18 ] = KEY_POWER,
121         [  1 ] = KEY_TV,             // DVR
122         [ 21 ] = KEY_DVD,            // DVD
123         [ 23 ] = KEY_AUDIO,          // music
124                                      // DVR mode / DVD mode / music mode
125
126         [ 27 ] = KEY_MUTE,           // mute
127         [  2 ] = KEY_LANGUAGE,       // MTS/SAP / audio / autoseek
128         [ 30 ] = KEY_SUBTITLE,       // closed captioning / subtitle / seek
129         [ 22 ] = KEY_ZOOM,           // full screen
130         [ 28 ] = KEY_VIDEO,          // video source / eject / delall
131         [ 29 ] = KEY_RESTART,        // playback / angle / del
132         [ 47 ] = KEY_SEARCH,         // scan / menu / playlist
133         [ 48 ] = KEY_CHANNEL,        // CH surfing / bookmark / memo
134
135         [ 49 ] = KEY_HELP,           // help
136         [ 50 ] = KEY_MODE,           // num/memo
137         [ 51 ] = KEY_ESC,            // cancel
138
139         [ 12 ] = KEY_UP,             // up
140         [ 16 ] = KEY_DOWN,           // down
141         [  8 ] = KEY_LEFT,           // left
142         [  4 ] = KEY_RIGHT,          // right
143         [  3 ] = KEY_SELECT,         // select
144
145         [ 31 ] = KEY_REWIND,         // rewind
146         [ 32 ] = KEY_PLAYPAUSE,      // play/pause
147         [ 41 ] = KEY_FORWARD,        // forward
148         [ 20 ] = KEY_AGAIN,          // repeat
149         [ 43 ] = KEY_RECORD,         // recording
150         [ 44 ] = KEY_STOP,           // stop
151         [ 45 ] = KEY_PLAY,           // play
152         [ 46 ] = KEY_SHUFFLE,        // snapshot / shuffle
153
154         [  0 ] = KEY_KP0,
155         [  5 ] = KEY_KP1,
156         [  6 ] = KEY_KP2,
157         [  7 ] = KEY_KP3,
158         [  9 ] = KEY_KP4,
159         [ 10 ] = KEY_KP5,
160         [ 11 ] = KEY_KP6,
161         [ 13 ] = KEY_KP7,
162         [ 14 ] = KEY_KP8,
163         [ 15 ] = KEY_KP9,
164
165         [ 42 ] = KEY_VOLUMEUP,
166         [ 17 ] = KEY_VOLUMEDOWN,
167         [ 24 ] = KEY_CHANNELUP,      // CH.tracking up
168         [ 25 ] = KEY_CHANNELDOWN,    // CH.tracking down
169
170         [ 19 ] = KEY_KPENTER,        // enter
171         [ 33 ] = KEY_KPDOT,          // . (decimal dot)
172 };
173
174 static IR_KEYTAB_TYPE avacssmart_codes[IR_KEYTAB_SIZE] = {
175         [ 30 ] = KEY_POWER,             // power
176         [ 28 ] = KEY_SEARCH,            // scan
177         [  7 ] = KEY_SELECT,            // source
178
179         [ 22 ] = KEY_VOLUMEUP,
180         [ 20 ] = KEY_VOLUMEDOWN,
181         [ 31 ] = KEY_CHANNELUP,
182         [ 23 ] = KEY_CHANNELDOWN,
183         [ 24 ] = KEY_MUTE,
184
185         [  2 ] = KEY_KP0,
186         [  1 ] = KEY_KP1,
187         [ 11 ] = KEY_KP2,
188         [ 27 ] = KEY_KP3,
189         [  5 ] = KEY_KP4,
190         [  9 ] = KEY_KP5,
191         [ 21 ] = KEY_KP6,
192         [  6 ] = KEY_KP7,
193         [ 10 ] = KEY_KP8,
194         [ 18 ] = KEY_KP9,
195         [ 16 ] = KEY_KPDOT,
196
197         [  3 ] = KEY_TUNER,             // tv/fm
198         [  4 ] = KEY_REWIND,            // fm tuning left or function left
199         [ 12 ] = KEY_FORWARD,           // fm tuning right or function right
200
201         [  0 ] = KEY_RECORD,
202         [  8 ] = KEY_STOP,
203         [ 17 ] = KEY_PLAY,
204
205         [ 25 ] = KEY_ZOOM,
206         [ 14 ] = KEY_MENU,              // function
207         [ 19 ] = KEY_AGAIN,             // recall
208         [ 29 ] = KEY_RESTART,           // reset
209
210 // FIXME
211         [ 13 ] = KEY_F21,               // mts
212         [ 15 ] = KEY_F22,               // min
213         [ 26 ] = KEY_F23,               // freeze
214 };
215
216 /* Alex Hermann <gaaf@gmx.net> */
217 static IR_KEYTAB_TYPE md2819_codes[IR_KEYTAB_SIZE] = {
218         [ 40 ] = KEY_KP1,
219         [ 24 ] = KEY_KP2,
220         [ 56 ] = KEY_KP3,
221         [ 36 ] = KEY_KP4,
222         [ 20 ] = KEY_KP5,
223         [ 52 ] = KEY_KP6,
224         [ 44 ] = KEY_KP7,
225         [ 28 ] = KEY_KP8,
226         [ 60 ] = KEY_KP9,
227         [ 34 ] = KEY_KP0,
228
229         [ 32 ] = KEY_TV,                // TV/FM
230         [ 16 ] = KEY_CD,                // CD
231         [ 48 ] = KEY_TEXT,              // TELETEXT
232         [  0 ] = KEY_POWER,             // POWER
233
234         [  8 ] = KEY_VIDEO,             // VIDEO
235         [  4 ] = KEY_AUDIO,             // AUDIO
236         [ 12 ] = KEY_ZOOM,              // FULL SCREEN
237
238         [ 18 ] = KEY_SUBTITLE,          // DISPLAY      - ???
239         [ 50 ] = KEY_REWIND,            // LOOP         - ???
240         [  2 ] = KEY_PRINT,             // PREVIEW      - ???
241
242         [ 42 ] = KEY_SEARCH,            // AUTOSCAN
243         [ 26 ] = KEY_SLEEP,             // FREEZE       - ???
244         [ 58 ] = KEY_SHUFFLE,           // SNAPSHOT     - ???
245         [ 10 ] = KEY_MUTE,              // MUTE
246
247         [ 38 ] = KEY_RECORD,            // RECORD
248         [ 22 ] = KEY_PAUSE,             // PAUSE
249         [ 54 ] = KEY_STOP,              // STOP
250         [  6 ] = KEY_PLAY,              // PLAY
251
252         [ 46 ] = KEY_RED,               // <RED>
253         [ 33 ] = KEY_GREEN,             // <GREEN>
254         [ 14 ] = KEY_YELLOW,            // <YELLOW>
255         [  1 ] = KEY_BLUE,              // <BLUE>
256
257         [ 30 ] = KEY_VOLUMEDOWN,        // VOLUME-
258         [ 62 ] = KEY_VOLUMEUP,          // VOLUME+
259         [ 17 ] = KEY_CHANNELDOWN,       // CHANNEL/PAGE-
260         [ 49 ] = KEY_CHANNELUP          // CHANNEL/PAGE+
261 };
262
263 static IR_KEYTAB_TYPE videomate_tv_pvr_codes[IR_KEYTAB_SIZE] = {
264         [ 20 ] = KEY_MUTE,
265         [ 36 ] = KEY_ZOOM,
266
267         [  1 ] = KEY_DVD,
268         [ 35 ] = KEY_RADIO,
269         [  0 ] = KEY_TV,
270
271         [ 10 ] = KEY_REWIND,
272         [  8 ] = KEY_PLAYPAUSE,
273         [ 15 ] = KEY_FORWARD,
274
275         [  2 ] = KEY_PREVIOUS,
276         [  7 ] = KEY_STOP,
277         [  6 ] = KEY_NEXT,
278
279         [ 12 ] = KEY_UP,
280         [ 14 ] = KEY_DOWN,
281         [ 11 ] = KEY_LEFT,
282         [ 13 ] = KEY_RIGHT,
283         [ 17 ] = KEY_OK,
284
285         [  3 ] = KEY_MENU,
286         [  9 ] = KEY_SETUP,
287         [  5 ] = KEY_VIDEO,
288         [ 34 ] = KEY_CHANNEL,
289
290         [ 18 ] = KEY_VOLUMEUP,
291         [ 21 ] = KEY_VOLUMEDOWN,
292         [ 16 ] = KEY_CHANNELUP,
293         [ 19 ] = KEY_CHANNELDOWN,
294
295         [  4 ] = KEY_RECORD,
296
297         [ 22 ] = KEY_KP1,
298         [ 23 ] = KEY_KP2,
299         [ 24 ] = KEY_KP3,
300         [ 25 ] = KEY_KP4,
301         [ 26 ] = KEY_KP5,
302         [ 27 ] = KEY_KP6,
303         [ 28 ] = KEY_KP7,
304         [ 29 ] = KEY_KP8,
305         [ 30 ] = KEY_KP9,
306         [ 31 ] = KEY_KP0,
307
308         [ 32 ] = KEY_LANGUAGE,
309         [ 33 ] = KEY_SLEEP,
310 };
311
312 /* Michael Tokarev <mjt@tls.msk.ru>
313    http://www.corpit.ru/mjt/beholdTV/remote_control.jpg
314    keytable is used by MANLI MTV00[12] and BeholdTV 40[13] at
315    least, and probably other cards too.
316    The "ascii-art picture" below (in comments, first row
317    is the keycode in hex, and subsequent row(s) shows
318    the button labels (several variants when appropriate)
319    helps to descide which keycodes to assign to the buttons.
320  */
321 static IR_KEYTAB_TYPE manli_codes[IR_KEYTAB_SIZE] = {
322
323         /*  0x1c            0x12  *
324          * FUNCTION         POWER *
325          *   FM              (|)  *
326          *                        */
327         [ 0x1c ] = KEY_RADIO,   /*XXX*/
328         [ 0x12 ] = KEY_POWER,
329
330         /*  0x01    0x02    0x03  *
331          *   1       2       3    *
332          *                        *
333          *  0x04    0x05    0x06  *
334          *   4       5       6    *
335          *                        *
336          *  0x07    0x08    0x09  *
337          *   7       8       9    *
338          *                        */
339         [ 0x01 ] = KEY_KP1,
340         [ 0x02 ] = KEY_KP2,
341         [ 0x03 ] = KEY_KP3,
342         [ 0x04 ] = KEY_KP4,
343         [ 0x05 ] = KEY_KP5,
344         [ 0x06 ] = KEY_KP6,
345         [ 0x07 ] = KEY_KP7,
346         [ 0x08 ] = KEY_KP8,
347         [ 0x09 ] = KEY_KP9,
348
349         /*  0x0a    0x00    0x17  *
350          * RECALL    0      +100  *
351          *                  PLUS  *
352          *                        */
353         [ 0x0a ] = KEY_AGAIN,   /*XXX KEY_REWIND? */
354         [ 0x00 ] = KEY_KP0,
355         [ 0x17 ] = KEY_DIGITS,  /*XXX*/
356
357         /*  0x14            0x10  *
358          *  MENU            INFO  *
359          *  OSD                   */
360         [ 0x14 ] = KEY_MENU,
361         [ 0x10 ] = KEY_INFO,
362
363         /*          0x0b          *
364          *           Up           *
365          *                        *
366          *  0x18    0x16    0x0c  *
367          *  Left     Ok     Right *
368          *                        *
369          *         0x015          *
370          *         Down           *
371          *                        */
372         [ 0x0b ] = KEY_UP,      /*XXX KEY_SCROLLUP? */
373         [ 0x18 ] = KEY_LEFT,    /*XXX KEY_BACK? */
374         [ 0x16 ] = KEY_OK,      /*XXX KEY_SELECT? KEY_ENTER? */
375         [ 0x0c ] = KEY_RIGHT,   /*XXX KEY_FORWARD? */
376         [ 0x15 ] = KEY_DOWN,    /*XXX KEY_SCROLLDOWN? */
377
378         /*  0x11            0x0d  *
379          *  TV/AV           MODE  *
380          *  SOURCE         STEREO *
381          *                        */
382         [ 0x11 ] = KEY_TV,      /*XXX*/
383         [ 0x0d ] = KEY_MODE,    /*XXX there's no KEY_STEREO */
384
385         /*  0x0f    0x1b    0x1a  *
386          *  AUDIO   Vol+    Chan+ *
387          *        TIMESHIFT???    *
388          *                        *
389          *  0x0e    0x1f    0x1e  *
390          *  SLEEP   Vol-    Chan- *
391          *                        */
392         [ 0x0f ] = KEY_AUDIO,
393         [ 0x1b ] = KEY_VOLUMEUP,
394         [ 0x1a ] = KEY_CHANNELUP,
395         [ 0x0e ] = KEY_SLEEP,   /*XXX maybe KEY_PAUSE */
396         [ 0x1f ] = KEY_VOLUMEDOWN,
397         [ 0x1e ] = KEY_CHANNELDOWN,
398
399         /*         0x13     0x19  *
400          *         MUTE   SNAPSHOT*
401          *                        */
402         [ 0x13 ] = KEY_MUTE,
403         [ 0x19 ] = KEY_RECORD,  /*XXX*/
404
405         // 0x1d unused ?
406 };
407 /* ---------------------------------------------------------------------- */
408
409 static int build_key(struct saa7134_dev *dev)
410 {
411         struct saa7134_ir *ir = dev->remote;
412         u32 gpio, data;
413
414         /* rising SAA7134_GPIO_GPRESCAN reads the status */
415         saa_clearb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN);
416         saa_setb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN);
417
418         gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2);
419         if (ir->polling) {
420                 if (ir->last_gpio == gpio)
421                         return 0;
422                 ir->last_gpio = gpio;
423         }
424
425         data = ir_extract_bits(gpio, ir->mask_keycode);
426         dprintk("build_key gpio=0x%x mask=0x%x data=%d\n",
427                 gpio, ir->mask_keycode, data);
428
429         if ((ir->mask_keydown  &&  (0 != (gpio & ir->mask_keydown))) ||
430             (ir->mask_keyup    &&  (0 == (gpio & ir->mask_keyup)))) {
431                 ir_input_keydown(&ir->dev,&ir->ir,data,data);
432         } else {
433                 ir_input_nokey(&ir->dev,&ir->ir);
434         }
435         return 0;
436 }
437
438 /* ---------------------------------------------------------------------- */
439
440 void saa7134_input_irq(struct saa7134_dev *dev)
441 {
442         struct saa7134_ir *ir = dev->remote;
443
444         if (!ir->polling)
445                 build_key(dev);
446 }
447
448 static void saa7134_input_timer(unsigned long data)
449 {
450         struct saa7134_dev *dev = (struct saa7134_dev*)data;
451         struct saa7134_ir *ir = dev->remote;
452         unsigned long timeout;
453
454         build_key(dev);
455         timeout = jiffies + (ir->polling * HZ / 1000);
456         mod_timer(&ir->timer, timeout);
457 }
458
459 int saa7134_input_init1(struct saa7134_dev *dev)
460 {
461         struct saa7134_ir *ir;
462         IR_KEYTAB_TYPE *ir_codes = NULL;
463         u32 mask_keycode = 0;
464         u32 mask_keydown = 0;
465         u32 mask_keyup   = 0;
466         int polling      = 0;
467         int ir_type      = IR_TYPE_OTHER;
468
469         if (!dev->has_remote)
470                 return -ENODEV;
471         if (disable_ir)
472                 return -ENODEV;
473
474         /* detect & configure */
475         switch (dev->board) {
476         case SAA7134_BOARD_FLYVIDEO2000:
477         case SAA7134_BOARD_FLYVIDEO3000:
478         case SAA7134_BOARD_FLYTVPLATINUM_FM:
479                 ir_codes     = flyvideo_codes;
480                 mask_keycode = 0xEC00000;
481                 mask_keydown = 0x0040000;
482                 break;
483         case SAA7134_BOARD_CINERGY400:
484         case SAA7134_BOARD_CINERGY600:
485         case SAA7134_BOARD_CINERGY600_MK3:
486                 ir_codes     = cinergy_codes;
487                 mask_keycode = 0x00003f;
488                 mask_keyup   = 0x040000;
489                 break;
490         case SAA7134_BOARD_ECS_TVP3XP:
491         case SAA7134_BOARD_ECS_TVP3XP_4CB5:
492                 ir_codes     = eztv_codes;
493                 mask_keycode = 0x00017c;
494                 mask_keyup   = 0x000002;
495                 polling      = 50; // ms
496                 break;
497         case SAA7134_BOARD_AVACSSMARTTV:
498                 ir_codes     = avacssmart_codes;
499                 mask_keycode = 0x00001F;
500                 mask_keyup   = 0x000020;
501                 polling      = 50; // ms
502                 break;
503         case SAA7134_BOARD_MD2819:
504         case SAA7134_BOARD_KWORLD_VSTREAM_XPERT:
505         case SAA7134_BOARD_AVERMEDIA_305:
506         case SAA7134_BOARD_AVERMEDIA_307:
507         case SAA7134_BOARD_AVERMEDIA_STUDIO_305:
508         case SAA7134_BOARD_AVERMEDIA_STUDIO_307:
509         case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
510                 ir_codes     = md2819_codes;
511                 mask_keycode = 0x0007C8;
512                 mask_keydown = 0x000010;
513                 polling      = 50; // ms
514                 /* Set GPIO pin2 to high to enable the IR controller */
515                 saa_setb(SAA7134_GPIO_GPMODE0, 0x4);
516                 saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4);
517                 break;
518         case SAA7134_BOARD_MANLI_MTV001:
519         case SAA7134_BOARD_MANLI_MTV002:
520                 ir_codes     = manli_codes;
521                 mask_keycode = 0x001f00;
522                 mask_keyup   = 0x004000;
523                 mask_keydown = 0x002000;
524                 polling      = 50; // ms
525                 break;
526         case SAA7134_BOARD_VIDEOMATE_TV_PVR:
527                 ir_codes     = videomate_tv_pvr_codes;
528                 mask_keycode = 0x00003F;
529                 mask_keyup   = 0x400000;
530                 polling      = 50; // ms
531                 break;
532         }
533         if (NULL == ir_codes) {
534                 printk("%s: Oops: IR config error [card=%d]\n",
535                        dev->name, dev->board);
536                 return -ENODEV;
537         }
538
539         ir = kmalloc(sizeof(*ir),GFP_KERNEL);
540         if (NULL == ir)
541                 return -ENOMEM;
542         memset(ir,0,sizeof(*ir));
543
544         /* init hardware-specific stuff */
545         ir->mask_keycode = mask_keycode;
546         ir->mask_keydown = mask_keydown;
547         ir->mask_keyup   = mask_keyup;
548         ir->polling      = polling;
549
550         /* init input device */
551         snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)",
552                  saa7134_boards[dev->board].name);
553         snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
554                  pci_name(dev->pci));
555
556         ir_input_init(&ir->dev, &ir->ir, ir_type, ir_codes);
557         ir->dev.name = ir->name;
558         ir->dev.phys = ir->phys;
559         ir->dev.id.bustype = BUS_PCI;
560         ir->dev.id.version = 1;
561         if (dev->pci->subsystem_vendor) {
562                 ir->dev.id.vendor  = dev->pci->subsystem_vendor;
563                 ir->dev.id.product = dev->pci->subsystem_device;
564         } else {
565                 ir->dev.id.vendor  = dev->pci->vendor;
566                 ir->dev.id.product = dev->pci->device;
567         }
568
569         /* all done */
570         dev->remote = ir;
571         if (ir->polling) {
572                 init_timer(&ir->timer);
573                 ir->timer.function = saa7134_input_timer;
574                 ir->timer.data     = (unsigned long)dev;
575                 ir->timer.expires  = jiffies + HZ;
576                 add_timer(&ir->timer);
577         }
578
579         input_register_device(&dev->remote->dev);
580         printk("%s: registered input device for IR\n",dev->name);
581         return 0;
582 }
583
584 void saa7134_input_fini(struct saa7134_dev *dev)
585 {
586         if (NULL == dev->remote)
587                 return;
588
589         input_unregister_device(&dev->remote->dev);
590         if (dev->remote->polling)
591                 del_timer_sync(&dev->remote->timer);
592         kfree(dev->remote);
593         dev->remote = NULL;
594 }
595
596 /* ----------------------------------------------------------------------
597  * Local variables:
598  * c-basic-offset: 8
599  * End:
600  */