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