initial commit with v2.6.9
[linux-2.6.9-moxart.git] / drivers / media / video / saa7134 / saa7134-input.c
bloba34447d6b913ff1cc9bce6a7f136da53e06ed44d
1 /*
2 * handle saa7134 IR remotes via linux kernel input layer.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include <linux/module.h>
21 #include <linux/init.h>
22 #include <linux/delay.h>
23 #include <linux/sched.h>
24 #include <linux/interrupt.h>
25 #include <linux/input.h>
27 #include "saa7134-reg.h"
28 #include "saa7134.h"
30 static unsigned int disable_ir = 0;
31 MODULE_PARM(disable_ir,"i");
32 MODULE_PARM_DESC(disable_ir,"disable infrared remote support");
34 static unsigned int ir_debug = 0;
35 MODULE_PARM(ir_debug,"i");
36 MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]");
38 #define dprintk(fmt, arg...) if (ir_debug) \
39 printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg)
41 /* ---------------------------------------------------------------------- */
43 static IR_KEYTAB_TYPE flyvideo_codes[IR_KEYTAB_SIZE] = {
44 [ 15 ] = KEY_KP0,
45 [ 3 ] = KEY_KP1,
46 [ 4 ] = KEY_KP2,
47 [ 5 ] = KEY_KP3,
48 [ 7 ] = KEY_KP4,
49 [ 8 ] = KEY_KP5,
50 [ 9 ] = KEY_KP6,
51 [ 11 ] = KEY_KP7,
52 [ 12 ] = KEY_KP8,
53 [ 13 ] = KEY_KP9,
55 [ 14 ] = KEY_TUNER, // Air/Cable
56 [ 17 ] = KEY_VIDEO, // Video
57 [ 21 ] = KEY_AUDIO, // Audio
58 [ 0 ] = KEY_POWER, // Pover
59 [ 2 ] = KEY_ZOOM, // Fullscreen
60 [ 27 ] = KEY_MUTE, // Mute
61 [ 20 ] = KEY_VOLUMEUP,
62 [ 23 ] = KEY_VOLUMEDOWN,
63 [ 18 ] = KEY_CHANNELUP, // Channel +
64 [ 19 ] = KEY_CHANNELDOWN, // Channel -
65 [ 6 ] = KEY_AGAIN, // Recal
66 [ 16 ] = KEY_KPENTER, // Enter
68 #if 1 /* FIXME */
69 [ 26 ] = KEY_F22, // Stereo
70 [ 24 ] = KEY_EDIT, // AV Source
71 #endif
74 static IR_KEYTAB_TYPE cinergy_codes[IR_KEYTAB_SIZE] = {
75 [ 0 ] = KEY_KP0,
76 [ 1 ] = KEY_KP1,
77 [ 2 ] = KEY_KP2,
78 [ 3 ] = KEY_KP3,
79 [ 4 ] = KEY_KP4,
80 [ 5 ] = KEY_KP5,
81 [ 6 ] = KEY_KP6,
82 [ 7 ] = KEY_KP7,
83 [ 8 ] = KEY_KP8,
84 [ 9 ] = KEY_KP9,
86 [ 0x0a ] = KEY_POWER,
87 [ 0x0b ] = KEY_PROG1, // app
88 [ 0x0c ] = KEY_ZOOM, // zoom/fullscreen
89 [ 0x0d ] = KEY_CHANNELUP, // channel
90 [ 0x0e ] = KEY_CHANNELDOWN, // channel-
91 [ 0x0f ] = KEY_VOLUMEUP,
92 [ 0x10 ] = KEY_VOLUMEDOWN,
93 [ 0x11 ] = KEY_TUNER, // AV
94 [ 0x12 ] = KEY_NUMLOCK, // -/--
95 [ 0x13 ] = KEY_AUDIO, // audio
96 [ 0x14 ] = KEY_MUTE,
97 [ 0x15 ] = KEY_UP,
98 [ 0x16 ] = KEY_DOWN,
99 [ 0x17 ] = KEY_LEFT,
100 [ 0x18 ] = KEY_RIGHT,
101 [ 0x19 ] = BTN_LEFT,
102 [ 0x1a ] = BTN_RIGHT,
103 [ 0x1b ] = KEY_WWW, // text
104 [ 0x1c ] = KEY_REWIND,
105 [ 0x1d ] = KEY_FORWARD,
106 [ 0x1e ] = KEY_RECORD,
107 [ 0x1f ] = KEY_PLAY,
108 [ 0x20 ] = KEY_PREVIOUSSONG,
109 [ 0x21 ] = KEY_NEXTSONG,
110 [ 0x22 ] = KEY_PAUSE,
111 [ 0x23 ] = KEY_STOP,
114 /* Alfons Geser <a.geser@cox.net>
115 * updates from Job D. R. Borges <jobdrb@ig.com.br> */
116 static IR_KEYTAB_TYPE eztv_codes[IR_KEYTAB_SIZE] = {
117 [ 18 ] = KEY_POWER,
118 [ 1 ] = KEY_TV, // DVR
119 [ 21 ] = KEY_DVD, // DVD
120 [ 23 ] = KEY_AUDIO, // music
121 // DVR mode / DVD mode / music mode
123 [ 27 ] = KEY_MUTE, // mute
124 [ 2 ] = KEY_LANGUAGE, // MTS/SAP / audio / autoseek
125 [ 30 ] = KEY_SUBTITLE, // closed captioning / subtitle / seek
126 [ 22 ] = KEY_ZOOM, // full screen
127 [ 28 ] = KEY_VIDEO, // video source / eject / delall
128 [ 29 ] = KEY_RESTART, // playback / angle / del
129 [ 47 ] = KEY_SEARCH, // scan / menu / playlist
130 [ 48 ] = KEY_CHANNEL, // CH surfing / bookmark / memo
132 [ 49 ] = KEY_HELP, // help
133 [ 50 ] = KEY_MODE, // num/memo
134 [ 51 ] = KEY_ESC, // cancel
136 [ 12 ] = KEY_UP, // up
137 [ 16 ] = KEY_DOWN, // down
138 [ 8 ] = KEY_LEFT, // left
139 [ 4 ] = KEY_RIGHT, // right
140 [ 3 ] = KEY_SELECT, // select
142 [ 31 ] = KEY_REWIND, // rewind
143 [ 32 ] = KEY_PLAYPAUSE, // play/pause
144 [ 41 ] = KEY_FORWARD, // forward
145 [ 20 ] = KEY_AGAIN, // repeat
146 [ 43 ] = KEY_RECORD, // recording
147 [ 44 ] = KEY_STOP, // stop
148 [ 45 ] = KEY_PLAY, // play
149 [ 46 ] = KEY_SHUFFLE, // snapshot / shuffle
151 [ 0 ] = KEY_KP0,
152 [ 5 ] = KEY_KP1,
153 [ 6 ] = KEY_KP2,
154 [ 7 ] = KEY_KP3,
155 [ 9 ] = KEY_KP4,
156 [ 10 ] = KEY_KP5,
157 [ 11 ] = KEY_KP6,
158 [ 13 ] = KEY_KP7,
159 [ 14 ] = KEY_KP8,
160 [ 15 ] = KEY_KP9,
162 [ 42 ] = KEY_VOLUMEUP,
163 [ 17 ] = KEY_VOLUMEDOWN,
164 [ 24 ] = KEY_CHANNELUP, // CH.tracking up
165 [ 25 ] = KEY_CHANNELDOWN, // CH.tracking down
167 [ 19 ] = KEY_KPENTER, // enter
168 [ 33 ] = KEY_KPDOT, // . (decimal dot)
171 static IR_KEYTAB_TYPE avacssmart_codes[IR_KEYTAB_SIZE] = {
172 [ 30 ] = KEY_POWER, // power
173 [ 28 ] = KEY_SEARCH, // scan
174 [ 7 ] = KEY_SELECT, // source
176 [ 22 ] = KEY_VOLUMEUP,
177 [ 20 ] = KEY_VOLUMEDOWN,
178 [ 31 ] = KEY_CHANNELUP,
179 [ 23 ] = KEY_CHANNELDOWN,
180 [ 24 ] = KEY_MUTE,
182 [ 2 ] = KEY_KP0,
183 [ 1 ] = KEY_KP1,
184 [ 11 ] = KEY_KP2,
185 [ 27 ] = KEY_KP3,
186 [ 5 ] = KEY_KP4,
187 [ 9 ] = KEY_KP5,
188 [ 21 ] = KEY_KP6,
189 [ 6 ] = KEY_KP7,
190 [ 10 ] = KEY_KP8,
191 [ 18 ] = KEY_KP9,
192 [ 16 ] = KEY_KPDOT,
194 [ 3 ] = KEY_TUNER, // tv/fm
195 [ 4 ] = KEY_REWIND, // fm tuning left or function left
196 [ 12 ] = KEY_FORWARD, // fm tuning right or function right
198 [ 0 ] = KEY_RECORD,
199 [ 8 ] = KEY_STOP,
200 [ 17 ] = KEY_PLAY,
202 [ 25 ] = KEY_ZOOM,
203 [ 14 ] = KEY_MENU, // function
204 [ 19 ] = KEY_AGAIN, // recall
205 [ 29 ] = KEY_RESTART, // reset
207 // FIXME
208 [ 13 ] = KEY_F21, // mts
209 [ 15 ] = KEY_F22, // min
210 [ 26 ] = KEY_F23, // freeze
212 /* ---------------------------------------------------------------------- */
214 static int build_key(struct saa7134_dev *dev)
216 struct saa7134_ir *ir = dev->remote;
217 u32 gpio, data;
219 /* rising SAA7134_GPIO_GPRESCAN reads the status */
220 saa_clearb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN);
221 saa_setb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN);
223 gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2);
224 if (ir->polling) {
225 if (ir->last_gpio == gpio)
226 return 0;
227 ir->last_gpio = gpio;
230 data = ir_extract_bits(gpio, ir->mask_keycode);
231 dprintk("build_key gpio=0x%x mask=0x%x data=%d\n",
232 gpio, ir->mask_keycode, data);
234 if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) ||
235 (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) {
236 ir_input_keydown(&ir->dev,&ir->ir,data,data);
237 } else {
238 ir_input_nokey(&ir->dev,&ir->ir);
240 return 0;
243 /* ---------------------------------------------------------------------- */
245 void saa7134_input_irq(struct saa7134_dev *dev)
247 struct saa7134_ir *ir = dev->remote;
249 if (!ir->polling)
250 build_key(dev);
253 static void saa7134_input_timer(unsigned long data)
255 struct saa7134_dev *dev = (struct saa7134_dev*)data;
256 struct saa7134_ir *ir = dev->remote;
257 unsigned long timeout;
259 build_key(dev);
260 timeout = jiffies + (ir->polling * HZ / 1000);
261 mod_timer(&ir->timer, timeout);
264 int saa7134_input_init1(struct saa7134_dev *dev)
266 struct saa7134_ir *ir;
267 IR_KEYTAB_TYPE *ir_codes = NULL;
268 u32 mask_keycode = 0;
269 u32 mask_keydown = 0;
270 u32 mask_keyup = 0;
271 int polling = 0;
272 int ir_type = IR_TYPE_OTHER;
274 if (!dev->has_remote)
275 return -ENODEV;
276 if (disable_ir)
277 return -ENODEV;
279 /* detect & configure */
280 switch (dev->board) {
281 case SAA7134_BOARD_FLYVIDEO2000:
282 case SAA7134_BOARD_FLYVIDEO3000:
283 ir_codes = flyvideo_codes;
284 mask_keycode = 0xEC00000;
285 mask_keydown = 0x0040000;
286 break;
287 case SAA7134_BOARD_CINERGY400:
288 case SAA7134_BOARD_CINERGY600:
289 ir_codes = cinergy_codes;
290 mask_keycode = 0x00003f;
291 mask_keyup = 0x040000;
292 break;
293 case SAA7134_BOARD_ECS_TVP3XP:
294 case SAA7134_BOARD_ECS_TVP3XP_4CB5:
295 ir_codes = eztv_codes;
296 mask_keycode = 0x00017c;
297 mask_keyup = 0x000002;
298 polling = 50; // ms
299 break;
300 case SAA7134_BOARD_AVACSSMARTTV:
301 ir_codes = avacssmart_codes;
302 mask_keycode = 0x00001F;
303 mask_keyup = 0x000020;
304 polling = 50; // ms
305 break;
307 if (NULL == ir_codes) {
308 printk("%s: Oops: IR config error [card=%d]\n",
309 dev->name, dev->board);
310 return -ENODEV;
313 ir = kmalloc(sizeof(*ir),GFP_KERNEL);
314 if (NULL == ir)
315 return -ENOMEM;
316 memset(ir,0,sizeof(*ir));
318 /* init hardware-specific stuff */
319 ir->mask_keycode = mask_keycode;
320 ir->mask_keydown = mask_keydown;
321 ir->mask_keyup = mask_keyup;
322 ir->polling = polling;
324 /* init input device */
325 snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)",
326 saa7134_boards[dev->board].name);
327 snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
328 pci_name(dev->pci));
330 ir_input_init(&ir->dev, &ir->ir, ir_type, ir_codes);
331 ir->dev.name = ir->name;
332 ir->dev.phys = ir->phys;
333 ir->dev.id.bustype = BUS_PCI;
334 ir->dev.id.version = 1;
335 if (dev->pci->subsystem_vendor) {
336 ir->dev.id.vendor = dev->pci->subsystem_vendor;
337 ir->dev.id.product = dev->pci->subsystem_device;
338 } else {
339 ir->dev.id.vendor = dev->pci->vendor;
340 ir->dev.id.product = dev->pci->device;
343 /* all done */
344 dev->remote = ir;
345 if (ir->polling) {
346 init_timer(&ir->timer);
347 ir->timer.function = saa7134_input_timer;
348 ir->timer.data = (unsigned long)dev;
349 ir->timer.expires = jiffies + HZ;
350 add_timer(&ir->timer);
353 input_register_device(&dev->remote->dev);
354 printk("%s: registered input device for IR\n",dev->name);
355 return 0;
358 void saa7134_input_fini(struct saa7134_dev *dev)
360 if (NULL == dev->remote)
361 return;
363 input_unregister_device(&dev->remote->dev);
364 if (dev->remote->polling)
365 del_timer_sync(&dev->remote->timer);
366 kfree(dev->remote);
367 dev->remote = NULL;
370 /* ----------------------------------------------------------------------
371 * Local variables:
372 * c-basic-offset: 8
373 * End: