VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / drivers / media / video / ir-kbd-gpio.c
1
2 /*
3  * Copyright (c) 2003 Gerd Knorr
4  * Copyright (c) 2003 Pavel Machek
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 #include <linux/module.h>
22 #include <linux/moduleparam.h>
23 #include <linux/init.h>
24 #include <linux/delay.h>
25 #include <linux/interrupt.h>
26 #include <linux/input.h>
27 #include <linux/pci.h>
28
29 #include <media/ir-common.h>
30
31 #include "bttv.h"
32
33 /* ---------------------------------------------------------------------- */
34
35 static IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE] = {
36         [ 34 ] = KEY_KP0,
37         [ 40 ] = KEY_KP1,
38         [ 24 ] = KEY_KP2,
39         [ 56 ] = KEY_KP3,
40         [ 36 ] = KEY_KP4,
41         [ 20 ] = KEY_KP5,
42         [ 52 ] = KEY_KP6,
43         [ 44 ] = KEY_KP7,
44         [ 28 ] = KEY_KP8,
45         [ 60 ] = KEY_KP9,
46
47         [ 48 ] = KEY_EJECTCD,     // Unmarked on my controller
48         [  0 ] = KEY_POWER, 
49         [ 18 ] = BTN_LEFT,        // DISPLAY/L
50         [ 50 ] = BTN_RIGHT,       // LOOP/R
51         [ 10 ] = KEY_MUTE,
52         [ 38 ] = KEY_RECORD,
53         [ 22 ] = KEY_PAUSE,
54         [ 54 ] = KEY_STOP,
55         [ 30 ] = KEY_VOLUMEDOWN,
56         [ 62 ] = KEY_VOLUMEUP,
57
58         [ 32 ] = KEY_TUNER,       // TV/FM
59         [ 16 ] = KEY_CD,
60         [  8 ] = KEY_VIDEO,
61         [  4 ] = KEY_AUDIO,
62         [ 12 ] = KEY_ZOOM,        // full screen
63         [  2 ] = KEY_INFO,        // preview
64         [ 42 ] = KEY_SEARCH,      // autoscan
65         [ 26 ] = KEY_STOP,        // freeze
66         [ 58 ] = KEY_RECORD,      // capture
67         [  6 ] = KEY_PLAY,        // unmarked
68         [ 46 ] = KEY_RED,         // unmarked
69         [ 14 ] = KEY_GREEN,       // unmarked
70
71         [ 33 ] = KEY_YELLOW,      // unmarked
72         [ 17 ] = KEY_CHANNELDOWN,
73         [ 49 ] = KEY_CHANNELUP,
74         [  1 ] = KEY_BLUE,        // unmarked
75 };
76
77 static IR_KEYTAB_TYPE winfast_codes[IR_KEYTAB_SIZE] = {
78         [  5 ] = KEY_KP1,
79         [  6 ] = KEY_KP2,
80         [  7 ] = KEY_KP3,
81         [  9 ] = KEY_KP4,
82         [ 10 ] = KEY_KP5,
83         [ 11 ] = KEY_KP6,
84         [ 13 ] = KEY_KP7,
85         [ 14 ] = KEY_KP8,
86         [ 15 ] = KEY_KP9,
87         [ 18 ] = KEY_KP0,
88
89         [  0 ] = KEY_POWER,
90 //      [ 27 ] = MTS button
91         [  2 ] = KEY_TUNER,     // TV/FM
92         [ 30 ] = KEY_VIDEO,
93 //      [ 22 ] = display button
94         [  4 ] = KEY_VOLUMEUP,
95         [  8 ] = KEY_VOLUMEDOWN,
96         [ 12 ] = KEY_CHANNELUP,
97         [ 16 ] = KEY_CHANNELDOWN,
98         [  3 ] = KEY_ZOOM,      // fullscreen
99         [ 31 ] = KEY_SUBTITLE,  // closed caption/teletext
100         [ 32 ] = KEY_SLEEP,
101 //      [ 41 ] = boss key
102         [ 20 ] = KEY_MUTE,
103         [ 43 ] = KEY_RED,
104         [ 44 ] = KEY_GREEN,
105         [ 45 ] = KEY_YELLOW,
106         [ 46 ] = KEY_BLUE,
107         [ 24 ] = KEY_KPPLUS,    //fine tune +
108         [ 25 ] = KEY_KPMINUS,   //fine tune -
109 //      [ 42 ] = picture in picture
110         [ 33 ] = KEY_KPDOT,
111         [ 19 ] = KEY_KPENTER,
112 //      [ 17 ] = recall
113         [ 34 ] = KEY_BACK,
114         [ 35 ] = KEY_PLAYPAUSE,
115         [ 36 ] = KEY_NEXT,
116 //      [ 37 ] = time shifting
117         [ 38 ] = KEY_STOP,
118         [ 39 ] = KEY_RECORD
119 //      [ 40 ] = snapshot
120 };
121
122 static IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = {
123         [  2 ] = KEY_KP0,
124         [  1 ] = KEY_KP1,
125         [ 11 ] = KEY_KP2,
126         [ 27 ] = KEY_KP3,
127         [  5 ] = KEY_KP4,
128         [  9 ] = KEY_KP5,
129         [ 21 ] = KEY_KP6,
130         [  6 ] = KEY_KP7,
131         [ 10 ] = KEY_KP8,
132         [ 18 ] = KEY_KP9,
133         
134         [  3 ] = KEY_TUNER,       // TV/FM
135         [  7 ] = KEY_SEARCH,      // scan
136         [ 28 ] = KEY_ZOOM,        // full screen
137         [ 30 ] = KEY_POWER,
138         [ 23 ] = KEY_VOLUMEDOWN,
139         [ 31 ] = KEY_VOLUMEUP,
140         [ 20 ] = KEY_CHANNELDOWN,
141         [ 22 ] = KEY_CHANNELUP,
142         [ 24 ] = KEY_MUTE,
143         
144         [  0 ] = KEY_LIST,        // source
145         [ 19 ] = KEY_INFO,        // loop
146         [ 16 ] = KEY_LAST,        // +100
147         [ 13 ] = KEY_CLEAR,       // reset
148         [ 12 ] = BTN_RIGHT,       // fun++
149         [  4 ] = BTN_LEFT,        // fun--
150         [ 14 ] = KEY_GOTO,        // function
151         [ 15 ] = KEY_STOP,         // freeze
152 };
153
154 /* ---------------------------------------------------------------------- */
155
156 struct IR {
157         struct bttv_sub_device  *sub;
158         struct input_dev        input;
159         struct ir_input_state   ir;
160         char                    name[32];
161         char                    phys[32];
162         u32                     mask_keycode;
163         u32                     mask_keydown;
164         u32                     mask_keyup;
165
166         int                     polling;
167         u32                     last_gpio;
168         struct work_struct      work;
169         struct timer_list       timer;
170 };
171
172 static int debug;
173 module_param(debug, int, 0644);    /* debug level (0,1,2) */
174
175 #define DEVNAME "ir-kbd-gpio"
176 #define dprintk(fmt, arg...)    if (debug) \
177         printk(KERN_DEBUG DEVNAME ": " fmt , ## arg)
178
179 static void ir_irq(struct bttv_sub_device *sub);
180 static int ir_probe(struct device *dev);
181 static int ir_remove(struct device *dev);
182
183 static struct bttv_sub_driver driver = {
184         .drv = {
185                 .name   = DEVNAME,
186                 .probe  = ir_probe,
187                 .remove = ir_remove,
188         },
189         .gpio_irq       = ir_irq,
190 };
191
192 /* ---------------------------------------------------------------------- */
193
194 static void ir_handle_key(struct IR *ir)
195 {
196         u32 gpio,data;
197
198         /* read gpio value */
199         gpio = bttv_gpio_read(ir->sub->core);
200         if (ir->polling) {
201                 if (ir->last_gpio == gpio)
202                         return;
203                 ir->last_gpio = gpio;
204         }
205         
206         /* extract data */
207         data = ir_extract_bits(gpio, ir->mask_keycode);
208         dprintk(DEVNAME ": irq gpio=0x%x code=%d | %s%s%s\n",
209                 gpio, data,
210                 ir->polling               ? "poll"  : "irq",
211                 (gpio & ir->mask_keydown) ? " down" : "",
212                 (gpio & ir->mask_keyup)   ? " up"   : "");
213
214         if (ir->mask_keydown) {
215                 /* bit set on keydown */
216                 if (gpio & ir->mask_keydown) {
217                         ir_input_keydown(&ir->input,&ir->ir,data,data);
218                 } else {
219                         ir_input_nokey(&ir->input,&ir->ir);
220                 }
221
222         } else if (ir->mask_keyup) {
223                 /* bit cleared on keydown */
224                 if (0 == (gpio & ir->mask_keyup)) {
225                         ir_input_keydown(&ir->input,&ir->ir,data,data);
226                 } else {
227                         ir_input_nokey(&ir->input,&ir->ir);
228                 }
229
230         } else {
231                 /* can't disturgissh keydown/up :-/ */
232                 ir_input_keydown(&ir->input,&ir->ir,data,data);
233                 ir_input_nokey(&ir->input,&ir->ir);
234         }
235 }
236
237 static void ir_irq(struct bttv_sub_device *sub)
238 {
239         struct IR *ir = dev_get_drvdata(&sub->dev);
240
241         if (!ir->polling)
242                 ir_handle_key(ir);
243 }
244
245 static void ir_timer(unsigned long data)
246 {
247         struct IR *ir = (struct IR*)data;
248
249         schedule_work(&ir->work);
250 }
251
252 static void ir_work(void *data)
253 {
254         struct IR *ir = data;
255         unsigned long timeout;
256
257         ir_handle_key(ir);
258         timeout = jiffies + (ir->polling * HZ / 1000);
259         mod_timer(&ir->timer, timeout);
260 }
261
262 /* ---------------------------------------------------------------------- */
263
264 static int ir_probe(struct device *dev)
265 {
266         struct bttv_sub_device *sub = to_bttv_sub_dev(dev);
267         struct IR *ir;
268         IR_KEYTAB_TYPE *ir_codes = NULL;
269         int ir_type = IR_TYPE_OTHER;
270
271         ir = kmalloc(sizeof(*ir),GFP_KERNEL);
272         if (NULL == ir)
273                 return -ENOMEM;
274         memset(ir,0,sizeof(*ir));
275
276         /* detect & configure */
277         switch (sub->core->type) {
278         case BTTV_AVERMEDIA:
279         case BTTV_AVPHONE98:
280         case BTTV_AVERMEDIA98:
281                 ir_codes         = ir_codes_avermedia;
282                 ir->mask_keycode = 0xf88000;
283                 ir->mask_keydown = 0x010000;
284                 ir->polling      = 50; // ms
285                 break;
286
287         case BTTV_PXELVWPLTVPAK:
288                 ir_codes         = ir_codes_pixelview;
289                 ir->mask_keycode = 0x003e00;
290                 ir->mask_keyup   = 0x010000;
291                 ir->polling      = 50; // ms
292                 break;
293         case BTTV_PV_BT878P_9B:
294         case BTTV_PV_BT878P_PLUS:
295                 ir_codes         = ir_codes_pixelview;
296                 ir->mask_keycode = 0x001f00;
297                 ir->mask_keyup   = 0x008000;
298                 ir->polling      = 50; // ms
299                 break;
300
301         case BTTV_WINFAST2000:
302                 ir_codes         = winfast_codes;
303                 ir->mask_keycode = 0x1f8;
304                 break;
305         case BTTV_MAGICTVIEW061:
306         case BTTV_MAGICTVIEW063:
307                 ir_codes         = winfast_codes;
308                 ir->mask_keycode = 0x0008e000;
309                 ir->mask_keydown = 0x00200000;
310                 break;
311         }
312         if (NULL == ir_codes) {
313                 kfree(ir);
314                 return -ENODEV;
315         }
316
317         /* init hardware-specific stuff */
318         bttv_gpio_inout(sub->core, ir->mask_keycode | ir->mask_keydown, 0);
319         ir->sub = sub;
320         
321         /* init input device */
322         snprintf(ir->name, sizeof(ir->name), "bttv IR (card=%d)",
323                  sub->core->type);
324         snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
325                  pci_name(sub->core->pci));
326
327         ir_input_init(&ir->input, &ir->ir, ir_type, ir_codes);
328         ir->input.name = ir->name;
329         ir->input.phys = ir->phys;
330         ir->input.id.bustype = BUS_PCI;
331         ir->input.id.version = 1;
332         if (sub->core->pci->subsystem_vendor) {
333                 ir->input.id.vendor  = sub->core->pci->subsystem_vendor;
334                 ir->input.id.product = sub->core->pci->subsystem_device;
335         } else {
336                 ir->input.id.vendor  = sub->core->pci->vendor;
337                 ir->input.id.product = sub->core->pci->device;
338         }
339
340         if (ir->polling) {
341                 INIT_WORK(&ir->work, ir_work, ir);
342                 init_timer(&ir->timer);
343                 ir->timer.function = ir_timer;
344                 ir->timer.data     = (unsigned long)ir;
345                 schedule_work(&ir->work);
346         }
347
348         /* all done */
349         dev_set_drvdata(dev,ir);
350         input_register_device(&ir->input);
351         printk(DEVNAME ": %s detected at %s\n",ir->input.name,ir->input.phys);
352
353         return 0;
354 }
355
356 static int ir_remove(struct device *dev)
357 {
358         struct IR *ir = dev_get_drvdata(dev);
359
360         if (ir->polling) {
361                 del_timer(&ir->timer);
362                 flush_scheduled_work();
363         }
364
365         input_unregister_device(&ir->input);
366         kfree(ir);
367         return 0;
368 }
369
370 /* ---------------------------------------------------------------------- */
371
372 MODULE_AUTHOR("Gerd Knorr, Pavel Machek");
373 MODULE_DESCRIPTION("input driver for bt8x8 gpio IR remote controls");
374 MODULE_LICENSE("GPL");
375
376 static int ir_init(void)
377 {
378         return bttv_sub_register(&driver, "remote");
379 }
380
381 static void ir_fini(void)
382 {
383         bttv_sub_unregister(&driver);
384 }
385
386 module_init(ir_init);
387 module_exit(ir_fini);
388
389
390 /*
391  * Local variables:
392  * c-basic-offset: 8
393  * End:
394  */