[PATCH] v4l: CX88 Update
[linux-2.6.git] / drivers / media / video / cx88 / cx88-input.c
1 /*
2  * $Id: cx88-input.c,v 1.15 2005/07/07 13:58:38 mchehab Exp $
3  *
4  * Device driver for GPIO attached remote control interfaces
5  * on Conexant 2388x based TV/DVB cards.
6  *
7  * Copyright (c) 2003 Pavel Machek
8  * Copyright (c) 2004 Gerd Knorr
9  * Copyright (c) 2004 Chris Pascoe
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24  */
25
26 #include <linux/init.h>
27 #include <linux/delay.h>
28 #include <linux/input.h>
29 #include <linux/pci.h>
30 #include <linux/module.h>
31 #include <linux/moduleparam.h>
32
33 #include <media/ir-common.h>
34
35 #include "cx88.h"
36
37 /* ---------------------------------------------------------------------- */
38
39 /* DigitalNow DNTV Live DVB-T Remote */
40 static IR_KEYTAB_TYPE ir_codes_dntv_live_dvb_t[IR_KEYTAB_SIZE] = {
41         [0x00] = KEY_ESC,               /* 'go up a level?' */
42         /* Keys 0 to 9 */
43         [0x0a] = KEY_KP0,
44         [0x01] = KEY_KP1,
45         [0x02] = KEY_KP2,
46         [0x03] = KEY_KP3,
47         [0x04] = KEY_KP4,
48         [0x05] = KEY_KP5,
49         [0x06] = KEY_KP6,
50         [0x07] = KEY_KP7,
51         [0x08] = KEY_KP8,
52         [0x09] = KEY_KP9,
53
54         [0x0b] = KEY_TUNER,             /* tv/fm */
55         [0x0c] = KEY_SEARCH,            /* scan */
56         [0x0d] = KEY_STOP,
57         [0x0e] = KEY_PAUSE,
58         [0x0f] = KEY_LIST,              /* source */
59
60         [0x10] = KEY_MUTE,
61         [0x11] = KEY_REWIND,            /* backward << */
62         [0x12] = KEY_POWER,
63         [0x13] = KEY_S,                 /* snap */
64         [0x14] = KEY_AUDIO,             /* stereo */
65         [0x15] = KEY_CLEAR,             /* reset */
66         [0x16] = KEY_PLAY,
67         [0x17] = KEY_ENTER,
68         [0x18] = KEY_ZOOM,              /* full screen */
69         [0x19] = KEY_FASTFORWARD,       /* forward >> */
70         [0x1a] = KEY_CHANNELUP,
71         [0x1b] = KEY_VOLUMEUP,
72         [0x1c] = KEY_INFO,              /* preview */
73         [0x1d] = KEY_RECORD,            /* record */
74         [0x1e] = KEY_CHANNELDOWN,
75         [0x1f] = KEY_VOLUMEDOWN,
76 };
77
78 /* ---------------------------------------------------------------------- */
79
80 /* IO-DATA BCTV7E Remote */
81 static IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE] = {
82         [0x40] = KEY_TV,
83         [0x20] = KEY_RADIO,             /* FM */
84         [0x60] = KEY_EPG,
85         [0x00] = KEY_POWER,
86
87         /* Keys 0 to 9 */
88         [0x44] = KEY_KP0,               /* 10 */
89         [0x50] = KEY_KP1,
90         [0x30] = KEY_KP2,
91         [0x70] = KEY_KP3,
92         [0x48] = KEY_KP4,
93         [0x28] = KEY_KP5,
94         [0x68] = KEY_KP6,
95         [0x58] = KEY_KP7,
96         [0x38] = KEY_KP8,
97         [0x78] = KEY_KP9,
98
99         [0x10] = KEY_L,                 /* Live */
100         [0x08] = KEY_T,                 /* Time Shift */
101
102         [0x18] = KEY_PLAYPAUSE,         /* Play */
103
104         [0x24] = KEY_ENTER,             /* 11 */
105         [0x64] = KEY_ESC,               /* 12 */
106         [0x04] = KEY_M,                 /* Multi */
107
108         [0x54] = KEY_VIDEO,
109         [0x34] = KEY_CHANNELUP,
110         [0x74] = KEY_VOLUMEUP,
111         [0x14] = KEY_MUTE,
112
113         [0x4c] = KEY_S,                 /* SVIDEO */
114         [0x2c] = KEY_CHANNELDOWN,
115         [0x6c] = KEY_VOLUMEDOWN,
116         [0x0c] = KEY_ZOOM,
117
118         [0x5c] = KEY_PAUSE,
119         [0x3c] = KEY_C,                 /* || (red) */
120         [0x7c] = KEY_RECORD,            /* recording */
121         [0x1c] = KEY_STOP,
122
123         [0x41] = KEY_REWIND,            /* backward << */
124         [0x21] = KEY_PLAY,
125         [0x61] = KEY_FASTFORWARD,       /* forward >> */
126         [0x01] = KEY_NEXT,              /* skip >| */
127 };
128
129 /* ---------------------------------------------------------------------- */
130
131 /* ADS Tech Instant TV DVB-T PCI Remote */
132 static IR_KEYTAB_TYPE ir_codes_adstech_dvb_t_pci[IR_KEYTAB_SIZE] = {
133         /* Keys 0 to 9 */
134         [0x4d] = KEY_0,
135         [0x57] = KEY_1,
136         [0x4f] = KEY_2,
137         [0x53] = KEY_3,
138         [0x56] = KEY_4,
139         [0x4e] = KEY_5,
140         [0x5e] = KEY_6,
141         [0x54] = KEY_7,
142         [0x4c] = KEY_8,
143         [0x5c] = KEY_9,
144
145         [0x5b] = KEY_POWER,
146         [0x5f] = KEY_MUTE,
147         [0x55] = KEY_GOTO,
148         [0x5d] = KEY_SEARCH,
149         [0x17] = KEY_EPG,               /* Guide */
150         [0x1f] = KEY_MENU,
151         [0x0f] = KEY_UP,
152         [0x46] = KEY_DOWN,
153         [0x16] = KEY_LEFT,
154         [0x1e] = KEY_RIGHT,
155         [0x0e] = KEY_SELECT,            /* Enter */
156         [0x5a] = KEY_INFO,
157         [0x52] = KEY_EXIT,
158         [0x59] = KEY_PREVIOUS,
159         [0x51] = KEY_NEXT,
160         [0x58] = KEY_REWIND,
161         [0x50] = KEY_FORWARD,
162         [0x44] = KEY_PLAYPAUSE,
163         [0x07] = KEY_STOP,
164         [0x1b] = KEY_RECORD,
165         [0x13] = KEY_TUNER,             /* Live */
166         [0x0a] = KEY_A,
167         [0x12] = KEY_B,
168         [0x03] = KEY_PROG1,             /* 1 */
169         [0x01] = KEY_PROG2,             /* 2 */
170         [0x00] = KEY_PROG3,             /* 3 */
171         [0x06] = KEY_DVD,
172         [0x48] = KEY_AUX,               /* Photo */
173         [0x40] = KEY_VIDEO,
174         [0x19] = KEY_AUDIO,             /* Music */
175         [0x0b] = KEY_CHANNELUP,
176         [0x08] = KEY_CHANNELDOWN,
177         [0x15] = KEY_VOLUMEUP,
178         [0x1c] = KEY_VOLUMEDOWN,
179 };
180
181 /* ---------------------------------------------------------------------- */
182
183 /* MSI TV@nywhere remote */
184 static IR_KEYTAB_TYPE ir_codes_msi_tvanywhere[IR_KEYTAB_SIZE] = {
185         /* Keys 0 to 9 */
186         [0x00] = KEY_0,
187         [0x01] = KEY_1,
188         [0x02] = KEY_2,
189         [0x03] = KEY_3,
190         [0x04] = KEY_4,
191         [0x05] = KEY_5,
192         [0x06] = KEY_6,
193         [0x07] = KEY_7,
194         [0x08] = KEY_8,
195         [0x09] = KEY_9,
196
197         [0x0c] = KEY_MUTE,
198         [0x0f] = KEY_SCREEN,            /* Full Screen */
199         [0x10] = KEY_F,                 /* Funtion */
200         [0x11] = KEY_T,                 /* Time shift */
201         [0x12] = KEY_POWER,
202         [0x13] = KEY_MEDIA,             /* MTS */
203         [0x14] = KEY_SLOW,
204         [0x16] = KEY_REWIND,            /* backward << */
205         [0x17] = KEY_ENTER,             /* Return */
206         [0x18] = KEY_FASTFORWARD,       /* forward >> */
207         [0x1a] = KEY_CHANNELUP,
208         [0x1b] = KEY_VOLUMEUP,
209         [0x1e] = KEY_CHANNELDOWN,
210         [0x1f] = KEY_VOLUMEDOWN,
211 };
212
213 /* ---------------------------------------------------------------------- */
214
215 struct cx88_IR {
216         struct cx88_core *core;
217         struct input_dev input;
218         struct ir_input_state ir;
219         char name[32];
220         char phys[32];
221
222         /* sample from gpio pin 16 */
223         int sampling;
224         u32 samples[16];
225         int scount;
226         unsigned long release;
227
228         /* poll external decoder */
229         int polling;
230         struct work_struct work;
231         struct timer_list timer;
232         u32 gpio_addr;
233         u32 last_gpio;
234         u32 mask_keycode;
235         u32 mask_keydown;
236         u32 mask_keyup;
237 };
238
239 static int ir_debug = 0;
240 module_param(ir_debug, int, 0644);      /* debug level [IR] */
241 MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
242
243 #define ir_dprintk(fmt, arg...) if (ir_debug) \
244         printk(KERN_DEBUG "%s IR: " fmt , ir->core->name, ## arg)
245
246 /* ---------------------------------------------------------------------- */
247
248 static void cx88_ir_handle_key(struct cx88_IR *ir)
249 {
250         struct cx88_core *core = ir->core;
251         u32 gpio, data;
252
253         /* read gpio value */
254         gpio = cx_read(ir->gpio_addr);
255         if (ir->polling) {
256                 if (ir->last_gpio == gpio)
257                         return;
258                 ir->last_gpio = gpio;
259         }
260
261         /* extract data */
262         data = ir_extract_bits(gpio, ir->mask_keycode);
263         ir_dprintk("irq gpio=0x%x code=%d | %s%s%s\n",
264                    gpio, data,
265                    ir->polling ? "poll" : "irq",
266                    (gpio & ir->mask_keydown) ? " down" : "",
267                    (gpio & ir->mask_keyup) ? " up" : "");
268
269         if (ir->mask_keydown) {
270                 /* bit set on keydown */
271                 if (gpio & ir->mask_keydown) {
272                         ir_input_keydown(&ir->input, &ir->ir, data, data);
273                 } else {
274                         ir_input_nokey(&ir->input, &ir->ir);
275                 }
276
277         } else if (ir->mask_keyup) {
278                 /* bit cleared on keydown */
279                 if (0 == (gpio & ir->mask_keyup)) {
280                         ir_input_keydown(&ir->input, &ir->ir, data, data);
281                 } else {
282                         ir_input_nokey(&ir->input, &ir->ir);
283                 }
284
285         } else {
286                 /* can't distinguish keydown/up :-/ */
287                 ir_input_keydown(&ir->input, &ir->ir, data, data);
288                 ir_input_nokey(&ir->input, &ir->ir);
289         }
290 }
291
292 static void ir_timer(unsigned long data)
293 {
294         struct cx88_IR *ir = (struct cx88_IR *)data;
295
296         schedule_work(&ir->work);
297 }
298
299 static void cx88_ir_work(void *data)
300 {
301         struct cx88_IR *ir = data;
302         unsigned long timeout;
303
304         cx88_ir_handle_key(ir);
305         timeout = jiffies + (ir->polling * HZ / 1000);
306         mod_timer(&ir->timer, timeout);
307 }
308
309 /* ---------------------------------------------------------------------- */
310
311 int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
312 {
313         struct cx88_IR *ir;
314         IR_KEYTAB_TYPE *ir_codes = NULL;
315         int ir_type = IR_TYPE_OTHER;
316
317         ir = kmalloc(sizeof(*ir), GFP_KERNEL);
318         if (NULL == ir)
319                 return -ENOMEM;
320         memset(ir, 0, sizeof(*ir));
321
322         /* detect & configure */
323         switch (core->board) {
324         case CX88_BOARD_DNTV_LIVE_DVB_T:
325         case CX88_BOARD_KWORLD_DVB_T:
326                 ir_codes = ir_codes_dntv_live_dvb_t;
327                 ir->gpio_addr = MO_GP1_IO;
328                 ir->mask_keycode = 0x1f;
329                 ir->mask_keyup = 0x60;
330                 ir->polling = 50; /* ms */
331                 break;
332         case CX88_BOARD_HAUPPAUGE:
333         case CX88_BOARD_HAUPPAUGE_DVB_T1:
334                 ir_codes = ir_codes_hauppauge_new;
335                 ir_type = IR_TYPE_RC5;
336                 ir->sampling = 1;
337                 break;
338         case CX88_BOARD_WINFAST2000XP_EXPERT:
339                 ir_codes = ir_codes_winfast;
340                 ir->gpio_addr = MO_GP0_IO;
341                 ir->mask_keycode = 0x8f8;
342                 ir->mask_keyup = 0x100;
343                 ir->polling = 1; /* ms */
344                 break;
345         case CX88_BOARD_IODATA_GVBCTV7E:
346                 ir_codes = ir_codes_iodata_bctv7e;
347                 ir->gpio_addr = MO_GP0_IO;
348                 ir->mask_keycode = 0xfd;
349                 ir->mask_keydown = 0x02;
350                 ir->polling = 5; /* ms */
351                 break;
352         case CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO:
353                 ir_codes = ir_codes_pixelview;
354                 ir->gpio_addr = MO_GP1_IO;
355                 ir->mask_keycode = 0x1f;
356                 ir->mask_keyup = 0x80;
357                 ir->polling = 1; /* ms */
358                 break;
359         case CX88_BOARD_ADSTECH_DVB_T_PCI:
360                 ir_codes = ir_codes_adstech_dvb_t_pci;
361                 ir->gpio_addr = MO_GP1_IO;
362                 ir->mask_keycode = 0xbf;
363                 ir->mask_keyup = 0x40;
364                 ir->polling = 50; /* ms */
365                 break;
366         case CX88_BOARD_MSI_TVANYWHERE_MASTER:
367                 ir_codes = ir_codes_msi_tvanywhere;
368                 ir->gpio_addr = MO_GP1_IO;
369                 ir->mask_keycode = 0x1f;
370                 ir->mask_keyup = 0x40;
371                 ir->polling = 1; /* ms */
372                 break;
373         }
374
375         if (NULL == ir_codes) {
376                 kfree(ir);
377                 return -ENODEV;
378         }
379
380         /* init input device */
381         snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)",
382                  cx88_boards[core->board].name);
383         snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci));
384
385         ir_input_init(&ir->input, &ir->ir, ir_type, ir_codes);
386         ir->input.name = ir->name;
387         ir->input.phys = ir->phys;
388         ir->input.id.bustype = BUS_PCI;
389         ir->input.id.version = 1;
390         if (pci->subsystem_vendor) {
391                 ir->input.id.vendor = pci->subsystem_vendor;
392                 ir->input.id.product = pci->subsystem_device;
393         } else {
394                 ir->input.id.vendor = pci->vendor;
395                 ir->input.id.product = pci->device;
396         }
397
398         /* record handles to ourself */
399         ir->core = core;
400         core->ir = ir;
401
402         if (ir->polling) {
403                 INIT_WORK(&ir->work, cx88_ir_work, ir);
404                 init_timer(&ir->timer);
405                 ir->timer.function = ir_timer;
406                 ir->timer.data = (unsigned long)ir;
407                 schedule_work(&ir->work);
408         }
409         if (ir->sampling) {
410                 core->pci_irqmask |= (1 << 18); /* IR_SMP_INT */
411                 cx_write(MO_DDS_IO, 0xa80a80);  /* 4 kHz sample rate */
412                 cx_write(MO_DDSCFG_IO, 0x5);    /* enable */
413         }
414
415         /* all done */
416         input_register_device(&ir->input);
417         printk("%s: registered IR remote control\n", core->name);
418
419         return 0;
420 }
421
422 int cx88_ir_fini(struct cx88_core *core)
423 {
424         struct cx88_IR *ir = core->ir;
425
426         /* skip detach on non attached boards */
427         if (NULL == ir)
428                 return 0;
429
430         if (ir->polling) {
431                 del_timer(&ir->timer);
432                 flush_scheduled_work();
433         }
434
435         input_unregister_device(&ir->input);
436         kfree(ir);
437
438         /* done */
439         core->ir = NULL;
440         return 0;
441 }
442
443 /* ---------------------------------------------------------------------- */
444
445 void cx88_ir_irq(struct cx88_core *core)
446 {
447         struct cx88_IR *ir = core->ir;
448         u32 samples, rc5;
449         int i;
450
451         if (NULL == ir)
452                 return;
453         if (!ir->sampling)
454                 return;
455
456         samples = cx_read(MO_SAMPLE_IO);
457         if (0 != samples && 0xffffffff != samples) {
458                 /* record sample data */
459                 if (ir->scount < ARRAY_SIZE(ir->samples))
460                         ir->samples[ir->scount++] = samples;
461                 return;
462         }
463         if (!ir->scount) {
464                 /* nothing to sample */
465                 if (ir->ir.keypressed && time_after(jiffies, ir->release))
466                         ir_input_nokey(&ir->input, &ir->ir);
467                 return;
468         }
469
470         /* have a complete sample */
471         if (ir->scount < ARRAY_SIZE(ir->samples))
472                 ir->samples[ir->scount++] = samples;
473         for (i = 0; i < ir->scount; i++)
474                 ir->samples[i] = ~ir->samples[i];
475         if (ir_debug)
476                 ir_dump_samples(ir->samples, ir->scount);
477
478         /* decode it */
479         switch (core->board) {
480         case CX88_BOARD_HAUPPAUGE:
481         case CX88_BOARD_HAUPPAUGE_DVB_T1:
482                 rc5 = ir_decode_biphase(ir->samples, ir->scount, 5, 7);
483                 ir_dprintk("biphase decoded: %x\n", rc5);
484                 if ((rc5 & 0xfffff000) != 0x3000)
485                         break;
486                 ir_input_keydown(&ir->input, &ir->ir, rc5 & 0x3f, rc5);
487                 ir->release = jiffies + msecs_to_jiffies(120);
488                 break;
489         }
490
491         ir->scount = 0;
492         return;
493 }
494
495 /* ---------------------------------------------------------------------- */
496
497 MODULE_AUTHOR("Gerd Knorr, Pavel Machek, Chris Pascoe");
498 MODULE_DESCRIPTION("input driver for cx88 GPIO-based IR remote controls");
499 MODULE_LICENSE("GPL");
500
501 /*
502  * Local variables:
503  * c-basic-offset: 8
504  * End:
505  */