blob: 82d28cbf289f1a1fe1bb5e22168ee32d8de2e001 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 *
3 * handle saa7134 IR remotes via linux kernel input layer.
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
21#include <linux/module.h>
22#include <linux/moduleparam.h>
23#include <linux/init.h>
24#include <linux/delay.h>
25#include <linux/sched.h>
26#include <linux/interrupt.h>
27#include <linux/input.h>
28
29#include "saa7134-reg.h"
30#include "saa7134.h"
31
32static unsigned int disable_ir = 0;
33module_param(disable_ir, int, 0444);
34MODULE_PARM_DESC(disable_ir,"disable infrared remote support");
35
36static unsigned int ir_debug = 0;
37module_param(ir_debug, int, 0644);
38MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]");
39
40#define dprintk(fmt, arg...) if (ir_debug) \
41 printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg)
Ricardo Cerqueiraac9cd972005-11-08 21:37:56 -080042#define i2cdprintk(fmt, arg...) if (ir_debug) \
43 printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -070044
45/* ---------------------------------------------------------------------- */
46
47static IR_KEYTAB_TYPE flyvideo_codes[IR_KEYTAB_SIZE] = {
48 [ 15 ] = KEY_KP0,
49 [ 3 ] = KEY_KP1,
50 [ 4 ] = KEY_KP2,
51 [ 5 ] = KEY_KP3,
52 [ 7 ] = KEY_KP4,
53 [ 8 ] = KEY_KP5,
54 [ 9 ] = KEY_KP6,
55 [ 11 ] = KEY_KP7,
56 [ 12 ] = KEY_KP8,
57 [ 13 ] = KEY_KP9,
58
Peter Missel0602fbb2006-01-09 18:21:23 -020059 [ 14 ] = KEY_MODE, // Air/Cable
Linus Torvalds1da177e2005-04-16 15:20:36 -070060 [ 17 ] = KEY_VIDEO, // Video
61 [ 21 ] = KEY_AUDIO, // Audio
Peter Missel0602fbb2006-01-09 18:21:23 -020062 [ 0 ] = KEY_POWER, // Power
63 [ 24 ] = KEY_TUNER, // AV Source
Linus Torvalds1da177e2005-04-16 15:20:36 -070064 [ 2 ] = KEY_ZOOM, // Fullscreen
Peter Missel0602fbb2006-01-09 18:21:23 -020065 [ 26 ] = KEY_LANGUAGE, // Stereo
Linus Torvalds1da177e2005-04-16 15:20:36 -070066 [ 27 ] = KEY_MUTE, // Mute
Peter Missel0602fbb2006-01-09 18:21:23 -020067 [ 20 ] = KEY_VOLUMEUP, // Volume +
68 [ 23 ] = KEY_VOLUMEDOWN, // Volume -
Linus Torvalds1da177e2005-04-16 15:20:36 -070069 [ 18 ] = KEY_CHANNELUP, // Channel +
70 [ 19 ] = KEY_CHANNELDOWN, // Channel -
Peter Missel0602fbb2006-01-09 18:21:23 -020071 [ 6 ] = KEY_AGAIN, // Recall
72 [ 16 ] = KEY_ENTER, // Enter
Linus Torvalds1da177e2005-04-16 15:20:36 -070073};
74
Peter Missel0602fbb2006-01-09 18:21:23 -020075
Linus Torvalds1da177e2005-04-16 15:20:36 -070076static IR_KEYTAB_TYPE cinergy_codes[IR_KEYTAB_SIZE] = {
77 [ 0 ] = KEY_KP0,
78 [ 1 ] = KEY_KP1,
79 [ 2 ] = KEY_KP2,
80 [ 3 ] = KEY_KP3,
81 [ 4 ] = KEY_KP4,
82 [ 5 ] = KEY_KP5,
83 [ 6 ] = KEY_KP6,
84 [ 7 ] = KEY_KP7,
85 [ 8 ] = KEY_KP8,
86 [ 9 ] = KEY_KP9,
87
88 [ 0x0a ] = KEY_POWER,
89 [ 0x0b ] = KEY_PROG1, // app
90 [ 0x0c ] = KEY_ZOOM, // zoom/fullscreen
91 [ 0x0d ] = KEY_CHANNELUP, // channel
92 [ 0x0e ] = KEY_CHANNELDOWN, // channel-
93 [ 0x0f ] = KEY_VOLUMEUP,
94 [ 0x10 ] = KEY_VOLUMEDOWN,
95 [ 0x11 ] = KEY_TUNER, // AV
96 [ 0x12 ] = KEY_NUMLOCK, // -/--
97 [ 0x13 ] = KEY_AUDIO, // audio
98 [ 0x14 ] = KEY_MUTE,
99 [ 0x15 ] = KEY_UP,
100 [ 0x16 ] = KEY_DOWN,
101 [ 0x17 ] = KEY_LEFT,
102 [ 0x18 ] = KEY_RIGHT,
103 [ 0x19 ] = BTN_LEFT,
104 [ 0x1a ] = BTN_RIGHT,
105 [ 0x1b ] = KEY_WWW, // text
106 [ 0x1c ] = KEY_REWIND,
107 [ 0x1d ] = KEY_FORWARD,
108 [ 0x1e ] = KEY_RECORD,
109 [ 0x1f ] = KEY_PLAY,
110 [ 0x20 ] = KEY_PREVIOUSSONG,
111 [ 0x21 ] = KEY_NEXTSONG,
112 [ 0x22 ] = KEY_PAUSE,
113 [ 0x23 ] = KEY_STOP,
114};
115
116/* Alfons Geser <a.geser@cox.net>
117 * updates from Job D. R. Borges <jobdrb@ig.com.br> */
118static IR_KEYTAB_TYPE eztv_codes[IR_KEYTAB_SIZE] = {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800119 [ 18 ] = KEY_POWER,
120 [ 1 ] = KEY_TV, // DVR
121 [ 21 ] = KEY_DVD, // DVD
122 [ 23 ] = KEY_AUDIO, // music
Mauro Carvalho Chehabf2421ca2005-11-08 21:37:45 -0800123 // DVR mode / DVD mode / music mode
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800125 [ 27 ] = KEY_MUTE, // mute
126 [ 2 ] = KEY_LANGUAGE, // MTS/SAP / audio / autoseek
127 [ 30 ] = KEY_SUBTITLE, // closed captioning / subtitle / seek
128 [ 22 ] = KEY_ZOOM, // full screen
129 [ 28 ] = KEY_VIDEO, // video source / eject / delall
130 [ 29 ] = KEY_RESTART, // playback / angle / del
131 [ 47 ] = KEY_SEARCH, // scan / menu / playlist
132 [ 48 ] = KEY_CHANNEL, // CH surfing / bookmark / memo
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800134 [ 49 ] = KEY_HELP, // help
135 [ 50 ] = KEY_MODE, // num/memo
136 [ 51 ] = KEY_ESC, // cancel
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137
138 [ 12 ] = KEY_UP, // up
139 [ 16 ] = KEY_DOWN, // down
140 [ 8 ] = KEY_LEFT, // left
141 [ 4 ] = KEY_RIGHT, // right
142 [ 3 ] = KEY_SELECT, // select
143
144 [ 31 ] = KEY_REWIND, // rewind
145 [ 32 ] = KEY_PLAYPAUSE, // play/pause
146 [ 41 ] = KEY_FORWARD, // forward
147 [ 20 ] = KEY_AGAIN, // repeat
148 [ 43 ] = KEY_RECORD, // recording
149 [ 44 ] = KEY_STOP, // stop
150 [ 45 ] = KEY_PLAY, // play
151 [ 46 ] = KEY_SHUFFLE, // snapshot / shuffle
152
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800153 [ 0 ] = KEY_KP0,
154 [ 5 ] = KEY_KP1,
155 [ 6 ] = KEY_KP2,
156 [ 7 ] = KEY_KP3,
157 [ 9 ] = KEY_KP4,
158 [ 10 ] = KEY_KP5,
159 [ 11 ] = KEY_KP6,
160 [ 13 ] = KEY_KP7,
161 [ 14 ] = KEY_KP8,
162 [ 15 ] = KEY_KP9,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800164 [ 42 ] = KEY_VOLUMEUP,
165 [ 17 ] = KEY_VOLUMEDOWN,
166 [ 24 ] = KEY_CHANNELUP, // CH.tracking up
167 [ 25 ] = KEY_CHANNELDOWN, // CH.tracking down
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800169 [ 19 ] = KEY_KPENTER, // enter
170 [ 33 ] = KEY_KPDOT, // . (decimal dot)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171};
172
173static IR_KEYTAB_TYPE avacssmart_codes[IR_KEYTAB_SIZE] = {
Mauro Carvalho Chehab330a1152005-07-12 13:59:01 -0700174 [ 30 ] = KEY_POWER, // power
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 [ 28 ] = KEY_SEARCH, // scan
Mauro Carvalho Chehab330a1152005-07-12 13:59:01 -0700176 [ 7 ] = KEY_SELECT, // source
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177
178 [ 22 ] = KEY_VOLUMEUP,
179 [ 20 ] = KEY_VOLUMEDOWN,
Mauro Carvalho Chehab330a1152005-07-12 13:59:01 -0700180 [ 31 ] = KEY_CHANNELUP,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181 [ 23 ] = KEY_CHANNELDOWN,
182 [ 24 ] = KEY_MUTE,
183
184 [ 2 ] = KEY_KP0,
Mauro Carvalho Chehab330a1152005-07-12 13:59:01 -0700185 [ 1 ] = KEY_KP1,
186 [ 11 ] = KEY_KP2,
187 [ 27 ] = KEY_KP3,
188 [ 5 ] = KEY_KP4,
189 [ 9 ] = KEY_KP5,
190 [ 21 ] = KEY_KP6,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 [ 6 ] = KEY_KP7,
Mauro Carvalho Chehab330a1152005-07-12 13:59:01 -0700192 [ 10 ] = KEY_KP8,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193 [ 18 ] = KEY_KP9,
194 [ 16 ] = KEY_KPDOT,
195
196 [ 3 ] = KEY_TUNER, // tv/fm
Mauro Carvalho Chehab330a1152005-07-12 13:59:01 -0700197 [ 4 ] = KEY_REWIND, // fm tuning left or function left
198 [ 12 ] = KEY_FORWARD, // fm tuning right or function right
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199
200 [ 0 ] = KEY_RECORD,
Mauro Carvalho Chehab330a1152005-07-12 13:59:01 -0700201 [ 8 ] = KEY_STOP,
202 [ 17 ] = KEY_PLAY,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203
204 [ 25 ] = KEY_ZOOM,
205 [ 14 ] = KEY_MENU, // function
206 [ 19 ] = KEY_AGAIN, // recall
207 [ 29 ] = KEY_RESTART, // reset
Mauro Carvalho Chehab330a1152005-07-12 13:59:01 -0700208 [ 26 ] = KEY_SHUFFLE, // snapshot/shuffle
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209
210// FIXME
211 [ 13 ] = KEY_F21, // mts
Mauro Carvalho Chehab330a1152005-07-12 13:59:01 -0700212 [ 15 ] = KEY_F22, // min
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213};
214
215/* Alex Hermann <gaaf@gmx.net> */
216static IR_KEYTAB_TYPE md2819_codes[IR_KEYTAB_SIZE] = {
217 [ 40 ] = KEY_KP1,
218 [ 24 ] = KEY_KP2,
219 [ 56 ] = KEY_KP3,
220 [ 36 ] = KEY_KP4,
221 [ 20 ] = KEY_KP5,
222 [ 52 ] = KEY_KP6,
223 [ 44 ] = KEY_KP7,
224 [ 28 ] = KEY_KP8,
225 [ 60 ] = KEY_KP9,
226 [ 34 ] = KEY_KP0,
227
228 [ 32 ] = KEY_TV, // TV/FM
229 [ 16 ] = KEY_CD, // CD
230 [ 48 ] = KEY_TEXT, // TELETEXT
231 [ 0 ] = KEY_POWER, // POWER
232
233 [ 8 ] = KEY_VIDEO, // VIDEO
234 [ 4 ] = KEY_AUDIO, // AUDIO
235 [ 12 ] = KEY_ZOOM, // FULL SCREEN
236
237 [ 18 ] = KEY_SUBTITLE, // DISPLAY - ???
238 [ 50 ] = KEY_REWIND, // LOOP - ???
239 [ 2 ] = KEY_PRINT, // PREVIEW - ???
240
241 [ 42 ] = KEY_SEARCH, // AUTOSCAN
242 [ 26 ] = KEY_SLEEP, // FREEZE - ???
243 [ 58 ] = KEY_SHUFFLE, // SNAPSHOT - ???
244 [ 10 ] = KEY_MUTE, // MUTE
245
246 [ 38 ] = KEY_RECORD, // RECORD
247 [ 22 ] = KEY_PAUSE, // PAUSE
248 [ 54 ] = KEY_STOP, // STOP
249 [ 6 ] = KEY_PLAY, // PLAY
250
251 [ 46 ] = KEY_RED, // <RED>
252 [ 33 ] = KEY_GREEN, // <GREEN>
253 [ 14 ] = KEY_YELLOW, // <YELLOW>
254 [ 1 ] = KEY_BLUE, // <BLUE>
255
256 [ 30 ] = KEY_VOLUMEDOWN, // VOLUME-
257 [ 62 ] = KEY_VOLUMEUP, // VOLUME+
258 [ 17 ] = KEY_CHANNELDOWN, // CHANNEL/PAGE-
259 [ 49 ] = KEY_CHANNELUP // CHANNEL/PAGE+
260};
261
262static IR_KEYTAB_TYPE videomate_tv_pvr_codes[IR_KEYTAB_SIZE] = {
263 [ 20 ] = KEY_MUTE,
264 [ 36 ] = KEY_ZOOM,
265
266 [ 1 ] = KEY_DVD,
267 [ 35 ] = KEY_RADIO,
268 [ 0 ] = KEY_TV,
269
270 [ 10 ] = KEY_REWIND,
271 [ 8 ] = KEY_PLAYPAUSE,
272 [ 15 ] = KEY_FORWARD,
273
274 [ 2 ] = KEY_PREVIOUS,
275 [ 7 ] = KEY_STOP,
276 [ 6 ] = KEY_NEXT,
277
278 [ 12 ] = KEY_UP,
279 [ 14 ] = KEY_DOWN,
280 [ 11 ] = KEY_LEFT,
281 [ 13 ] = KEY_RIGHT,
282 [ 17 ] = KEY_OK,
283
284 [ 3 ] = KEY_MENU,
285 [ 9 ] = KEY_SETUP,
286 [ 5 ] = KEY_VIDEO,
287 [ 34 ] = KEY_CHANNEL,
288
289 [ 18 ] = KEY_VOLUMEUP,
290 [ 21 ] = KEY_VOLUMEDOWN,
291 [ 16 ] = KEY_CHANNELUP,
292 [ 19 ] = KEY_CHANNELDOWN,
293
294 [ 4 ] = KEY_RECORD,
295
296 [ 22 ] = KEY_KP1,
297 [ 23 ] = KEY_KP2,
298 [ 24 ] = KEY_KP3,
299 [ 25 ] = KEY_KP4,
300 [ 26 ] = KEY_KP5,
301 [ 27 ] = KEY_KP6,
302 [ 28 ] = KEY_KP7,
303 [ 29 ] = KEY_KP8,
304 [ 30 ] = KEY_KP9,
305 [ 31 ] = KEY_KP0,
306
307 [ 32 ] = KEY_LANGUAGE,
308 [ 33 ] = KEY_SLEEP,
309};
Mauro Carvalho Chehabac19ecc2005-06-23 22:05:09 -0700310
311/* Michael Tokarev <mjt@tls.msk.ru>
312 http://www.corpit.ru/mjt/beholdTV/remote_control.jpg
313 keytable is used by MANLI MTV00[12] and BeholdTV 40[13] at
314 least, and probably other cards too.
315 The "ascii-art picture" below (in comments, first row
316 is the keycode in hex, and subsequent row(s) shows
317 the button labels (several variants when appropriate)
318 helps to descide which keycodes to assign to the buttons.
319 */
320static IR_KEYTAB_TYPE manli_codes[IR_KEYTAB_SIZE] = {
321
322 /* 0x1c 0x12 *
323 * FUNCTION POWER *
324 * FM (|) *
325 * */
326 [ 0x1c ] = KEY_RADIO, /*XXX*/
327 [ 0x12 ] = KEY_POWER,
328
329 /* 0x01 0x02 0x03 *
330 * 1 2 3 *
331 * *
332 * 0x04 0x05 0x06 *
333 * 4 5 6 *
334 * *
335 * 0x07 0x08 0x09 *
336 * 7 8 9 *
337 * */
338 [ 0x01 ] = KEY_KP1,
339 [ 0x02 ] = KEY_KP2,
340 [ 0x03 ] = KEY_KP3,
341 [ 0x04 ] = KEY_KP4,
342 [ 0x05 ] = KEY_KP5,
343 [ 0x06 ] = KEY_KP6,
344 [ 0x07 ] = KEY_KP7,
345 [ 0x08 ] = KEY_KP8,
346 [ 0x09 ] = KEY_KP9,
347
348 /* 0x0a 0x00 0x17 *
349 * RECALL 0 +100 *
350 * PLUS *
351 * */
352 [ 0x0a ] = KEY_AGAIN, /*XXX KEY_REWIND? */
353 [ 0x00 ] = KEY_KP0,
354 [ 0x17 ] = KEY_DIGITS, /*XXX*/
355
356 /* 0x14 0x10 *
357 * MENU INFO *
358 * OSD */
359 [ 0x14 ] = KEY_MENU,
360 [ 0x10 ] = KEY_INFO,
361
362 /* 0x0b *
363 * Up *
364 * *
365 * 0x18 0x16 0x0c *
366 * Left Ok Right *
367 * *
368 * 0x015 *
369 * Down *
370 * */
371 [ 0x0b ] = KEY_UP, /*XXX KEY_SCROLLUP? */
372 [ 0x18 ] = KEY_LEFT, /*XXX KEY_BACK? */
373 [ 0x16 ] = KEY_OK, /*XXX KEY_SELECT? KEY_ENTER? */
374 [ 0x0c ] = KEY_RIGHT, /*XXX KEY_FORWARD? */
375 [ 0x15 ] = KEY_DOWN, /*XXX KEY_SCROLLDOWN? */
376
377 /* 0x11 0x0d *
378 * TV/AV MODE *
379 * SOURCE STEREO *
380 * */
381 [ 0x11 ] = KEY_TV, /*XXX*/
382 [ 0x0d ] = KEY_MODE, /*XXX there's no KEY_STEREO */
383
384 /* 0x0f 0x1b 0x1a *
385 * AUDIO Vol+ Chan+ *
386 * TIMESHIFT??? *
387 * *
388 * 0x0e 0x1f 0x1e *
389 * SLEEP Vol- Chan- *
390 * */
391 [ 0x0f ] = KEY_AUDIO,
392 [ 0x1b ] = KEY_VOLUMEUP,
393 [ 0x1a ] = KEY_CHANNELUP,
394 [ 0x0e ] = KEY_SLEEP, /*XXX maybe KEY_PAUSE */
395 [ 0x1f ] = KEY_VOLUMEDOWN,
396 [ 0x1e ] = KEY_CHANNELDOWN,
397
398 /* 0x13 0x19 *
399 * MUTE SNAPSHOT*
400 * */
401 [ 0x13 ] = KEY_MUTE,
402 [ 0x19 ] = KEY_RECORD, /*XXX*/
403
404 // 0x1d unused ?
405};
Nickolay V. Shmyrev6b961442005-11-08 21:36:22 -0800406
407
Nickolay V. Shmyrevdcd555e2005-11-08 21:36:23 -0800408/* Mike Baikov <mike@baikov.com> */
Nickolay V. Shmyrev6b961442005-11-08 21:36:22 -0800409static IR_KEYTAB_TYPE gotview7135_codes[IR_KEYTAB_SIZE] = {
410
411 [ 33 ] = KEY_POWER,
412 [ 105] = KEY_TV,
413 [ 51 ] = KEY_KP0,
414 [ 81 ] = KEY_KP1,
415 [ 49 ] = KEY_KP2,
416 [ 113] = KEY_KP3,
417 [ 59 ] = KEY_KP4,
418 [ 88 ] = KEY_KP5,
419 [ 65 ] = KEY_KP6,
420 [ 72 ] = KEY_KP7,
421 [ 48 ] = KEY_KP8,
422 [ 83 ] = KEY_KP9,
423 [ 115] = KEY_AGAIN, /* LOOP */
424 [ 10 ] = KEY_AUDIO,
425 [ 97 ] = KEY_PRINT, /* PREVIEW */
426 [ 122] = KEY_VIDEO,
427 [ 32 ] = KEY_CHANNELUP,
428 [ 64 ] = KEY_CHANNELDOWN,
429 [ 24 ] = KEY_VOLUMEDOWN,
430 [ 80 ] = KEY_VOLUMEUP,
431 [ 16 ] = KEY_MUTE,
432 [ 74 ] = KEY_SEARCH,
433 [ 123] = KEY_SHUFFLE, /* SNAPSHOT */
434 [ 34 ] = KEY_RECORD,
435 [ 98 ] = KEY_STOP,
436 [ 120] = KEY_PLAY,
437 [ 57 ] = KEY_REWIND,
438 [ 89 ] = KEY_PAUSE,
439 [ 25 ] = KEY_FORWARD,
440 [ 9 ] = KEY_ZOOM,
441
442 [ 82 ] = KEY_F21, /* LIVE TIMESHIFT */
443 [ 26 ] = KEY_F22, /* MIN TIMESHIFT */
444 [ 58 ] = KEY_F23, /* TIMESHIFT */
445 [ 112] = KEY_F24, /* NORMAL TIMESHIFT */
446};
447
Ricardo Cerqueiraac9cd972005-11-08 21:37:56 -0800448static IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = {
449 [ 0x3 ] = KEY_POWER,
450 [ 0x6f ] = KEY_MUTE,
451 [ 0x10 ] = KEY_BACKSPACE, /* Recall */
452
453 [ 0x11 ] = KEY_KP0,
454 [ 0x4 ] = KEY_KP1,
455 [ 0x5 ] = KEY_KP2,
456 [ 0x6 ] = KEY_KP3,
457 [ 0x8 ] = KEY_KP4,
458 [ 0x9 ] = KEY_KP5,
459 [ 0xa ] = KEY_KP6,
460 [ 0xc ] = KEY_KP7,
461 [ 0xd ] = KEY_KP8,
462 [ 0xe ] = KEY_KP9,
463 [ 0x12 ] = KEY_KPDOT, /* 100+ */
464
465 [ 0x7 ] = KEY_VOLUMEUP,
466 [ 0xb ] = KEY_VOLUMEDOWN,
467 [ 0x1a ] = KEY_KPPLUS,
468 [ 0x18 ] = KEY_KPMINUS,
469 [ 0x15 ] = KEY_UP,
470 [ 0x1d ] = KEY_DOWN,
471 [ 0xf ] = KEY_CHANNELUP,
472 [ 0x13 ] = KEY_CHANNELDOWN,
473 [ 0x48 ] = KEY_ZOOM,
474
475 [ 0x1b ] = KEY_VIDEO, /* Video source */
476 [ 0x49 ] = KEY_LANGUAGE, /* MTS Select */
477 [ 0x19 ] = KEY_SEARCH, /* Auto Scan */
478
479 [ 0x4b ] = KEY_RECORD,
480 [ 0x46 ] = KEY_PLAY,
481 [ 0x45 ] = KEY_PAUSE, /* Pause */
482 [ 0x44 ] = KEY_STOP,
483 [ 0x40 ] = KEY_FORWARD, /* Forward ? */
484 [ 0x42 ] = KEY_REWIND, /* Backward ? */
485
486};
487
Pavel Mihaylovc3d93192005-11-08 21:38:43 -0800488/* Mapping for the 28 key remote control as seen at
489 http://www.sednacomputer.com/photo/cardbus-tv.jpg
490 Pavel Mihaylov <bin@bash.info> */
Ricardo Cerqueira17ce1ff2005-11-08 21:38:47 -0800491static IR_KEYTAB_TYPE pctv_sedna_codes[IR_KEYTAB_SIZE] = {
Pavel Mihaylovc3d93192005-11-08 21:38:43 -0800492 [ 0 ] = KEY_KP0,
493 [ 1 ] = KEY_KP1,
494 [ 2 ] = KEY_KP2,
495 [ 3 ] = KEY_KP3,
496 [ 4 ] = KEY_KP4,
497 [ 5 ] = KEY_KP5,
498 [ 6 ] = KEY_KP6,
499 [ 7 ] = KEY_KP7,
500 [ 8 ] = KEY_KP8,
501 [ 9 ] = KEY_KP9,
502
503 [ 0x0a ] = KEY_AGAIN, /* Recall */
504 [ 0x0b ] = KEY_CHANNELUP,
505 [ 0x0c ] = KEY_VOLUMEUP,
506 [ 0x0d ] = KEY_MODE, /* Stereo */
507 [ 0x0e ] = KEY_STOP,
508 [ 0x0f ] = KEY_PREVIOUSSONG,
509 [ 0x10 ] = KEY_ZOOM,
510 [ 0x11 ] = KEY_TUNER, /* Source */
511 [ 0x12 ] = KEY_POWER,
512 [ 0x13 ] = KEY_MUTE,
513 [ 0x15 ] = KEY_CHANNELDOWN,
514 [ 0x18 ] = KEY_VOLUMEDOWN,
515 [ 0x19 ] = KEY_SHUFFLE, /* Snapshot */
516 [ 0x1a ] = KEY_NEXTSONG,
517 [ 0x1b ] = KEY_TEXT, /* Time Shift */
518 [ 0x1c ] = KEY_RADIO, /* FM Radio */
519 [ 0x1d ] = KEY_RECORD,
520 [ 0x1e ] = KEY_PAUSE,
521};
522
523
Ricardo Cerqueiraac9cd972005-11-08 21:37:56 -0800524/* -------------------- GPIO generic keycode builder -------------------- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525
526static int build_key(struct saa7134_dev *dev)
527{
528 struct saa7134_ir *ir = dev->remote;
529 u32 gpio, data;
530
531 /* rising SAA7134_GPIO_GPRESCAN reads the status */
532 saa_clearb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN);
533 saa_setb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN);
534
535 gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800536 if (ir->polling) {
537 if (ir->last_gpio == gpio)
538 return 0;
539 ir->last_gpio = gpio;
540 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800542 data = ir_extract_bits(gpio, ir->mask_keycode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 dprintk("build_key gpio=0x%x mask=0x%x data=%d\n",
544 gpio, ir->mask_keycode, data);
545
Peter Missel0602fbb2006-01-09 18:21:23 -0200546 if (ir->polling) {
547 if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) ||
548 (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) {
549 ir_input_keydown(ir->dev, &ir->ir, data, data);
550 } else {
551 ir_input_nokey(ir->dev, &ir->ir);
552 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 }
Peter Missel0602fbb2006-01-09 18:21:23 -0200554 else { /* IRQ driven mode - handle key press and release in one go */
555 if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) ||
556 (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) {
557 ir_input_keydown(ir->dev, &ir->ir, data, data);
558 ir_input_nokey(ir->dev, &ir->ir);
559 }
560 }
561
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 return 0;
563}
564
Ricardo Cerqueiraac9cd972005-11-08 21:37:56 -0800565/* --------------------- Chip specific I2C key builders ----------------- */
566
567static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
568{
569 unsigned char b;
570
571 /* poll IR chip */
572 if (1 != i2c_master_recv(&ir->c,&b,1)) {
573 i2cdprintk("read error\n");
574 return -EIO;
575 }
576
577 /* no button press */
578 if (b==0)
579 return 0;
580
581 /* repeating */
582 if (b & 0x80)
583 return 1;
584
585 *ir_key = b;
586 *ir_raw = b;
587 return 1;
588}
589
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590void saa7134_input_irq(struct saa7134_dev *dev)
591{
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800592 struct saa7134_ir *ir = dev->remote;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800594 if (!ir->polling)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 build_key(dev);
596}
597
598static void saa7134_input_timer(unsigned long data)
599{
600 struct saa7134_dev *dev = (struct saa7134_dev*)data;
601 struct saa7134_ir *ir = dev->remote;
602 unsigned long timeout;
603
604 build_key(dev);
605 timeout = jiffies + (ir->polling * HZ / 1000);
606 mod_timer(&ir->timer, timeout);
607}
608
609int saa7134_input_init1(struct saa7134_dev *dev)
610{
611 struct saa7134_ir *ir;
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500612 struct input_dev *input_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 IR_KEYTAB_TYPE *ir_codes = NULL;
614 u32 mask_keycode = 0;
615 u32 mask_keydown = 0;
616 u32 mask_keyup = 0;
617 int polling = 0;
618 int ir_type = IR_TYPE_OTHER;
619
Ricardo Cerqueiracb2444d2005-11-08 21:38:47 -0800620 if (dev->has_remote != SAA7134_REMOTE_GPIO)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 return -ENODEV;
622 if (disable_ir)
623 return -ENODEV;
624
625 /* detect & configure */
626 switch (dev->board) {
627 case SAA7134_BOARD_FLYVIDEO2000:
628 case SAA7134_BOARD_FLYVIDEO3000:
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800629 case SAA7134_BOARD_FLYTVPLATINUM_FM:
Arnaud Patard6af90ab2005-11-08 21:36:55 -0800630 case SAA7134_BOARD_FLYTVPLATINUM_MINI2:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 ir_codes = flyvideo_codes;
632 mask_keycode = 0xEC00000;
633 mask_keydown = 0x0040000;
634 break;
635 case SAA7134_BOARD_CINERGY400:
636 case SAA7134_BOARD_CINERGY600:
637 case SAA7134_BOARD_CINERGY600_MK3:
638 ir_codes = cinergy_codes;
639 mask_keycode = 0x00003f;
640 mask_keyup = 0x040000;
641 break;
642 case SAA7134_BOARD_ECS_TVP3XP:
643 case SAA7134_BOARD_ECS_TVP3XP_4CB5:
Mauro Carvalho Chehab330a1152005-07-12 13:59:01 -0700644 ir_codes = eztv_codes;
645 mask_keycode = 0x00017c;
646 mask_keyup = 0x000002;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 polling = 50; // ms
Mauro Carvalho Chehab330a1152005-07-12 13:59:01 -0700648 break;
649 case SAA7134_BOARD_KWORLD_XPERT:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 case SAA7134_BOARD_AVACSSMARTTV:
Mauro Carvalho Chehab330a1152005-07-12 13:59:01 -0700651 ir_codes = avacssmart_codes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 mask_keycode = 0x00001F;
653 mask_keyup = 0x000020;
654 polling = 50; // ms
655 break;
656 case SAA7134_BOARD_MD2819:
Mauro Carvalho Chehabac19ecc2005-06-23 22:05:09 -0700657 case SAA7134_BOARD_KWORLD_VSTREAM_XPERT:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 case SAA7134_BOARD_AVERMEDIA_305:
659 case SAA7134_BOARD_AVERMEDIA_307:
Mauro Carvalho Chehabac19ecc2005-06-23 22:05:09 -0700660 case SAA7134_BOARD_AVERMEDIA_STUDIO_305:
661 case SAA7134_BOARD_AVERMEDIA_STUDIO_307:
662 case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 ir_codes = md2819_codes;
664 mask_keycode = 0x0007C8;
665 mask_keydown = 0x000010;
666 polling = 50; // ms
667 /* Set GPIO pin2 to high to enable the IR controller */
668 saa_setb(SAA7134_GPIO_GPMODE0, 0x4);
669 saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4);
670 break;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800671 case SAA7134_BOARD_KWORLD_TERMINATOR:
James R. Webbdc2286c2005-11-08 21:37:00 -0800672 ir_codes = avacssmart_codes;
673 mask_keycode = 0x00001f;
674 mask_keyup = 0x000060;
675 polling = 50; // ms
676 break;
Mauro Carvalho Chehabac19ecc2005-06-23 22:05:09 -0700677 case SAA7134_BOARD_MANLI_MTV001:
678 case SAA7134_BOARD_MANLI_MTV002:
Nickolay V. Shmyreva8ff4172005-11-08 21:36:16 -0800679 case SAA7134_BOARD_BEHOLD_409FM:
Mauro Carvalho Chehabac19ecc2005-06-23 22:05:09 -0700680 ir_codes = manli_codes;
681 mask_keycode = 0x001f00;
682 mask_keyup = 0x004000;
Mauro Carvalho Chehabac19ecc2005-06-23 22:05:09 -0700683 polling = 50; // ms
684 break;
Ricardo Cerqueira17ce1ff2005-11-08 21:38:47 -0800685 case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS:
686 ir_codes = pctv_sedna_codes;
Pavel Mihaylovc3d93192005-11-08 21:38:43 -0800687 mask_keycode = 0x001f00;
688 mask_keyup = 0x004000;
689 polling = 50; // ms
690 break;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800691 case SAA7134_BOARD_GOTVIEW_7135:
Nickolay V. Shmyrev6b961442005-11-08 21:36:22 -0800692 ir_codes = gotview7135_codes;
693 mask_keycode = 0x0003EC;
694 mask_keyup = 0x008000;
695 mask_keydown = 0x000010;
696 polling = 50; // ms
697 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 case SAA7134_BOARD_VIDEOMATE_TV_PVR:
Nickolay V. Shmyrev2a9a9a82006-01-09 15:25:33 -0200699 case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS:
Mauro Carvalho Chehab330a1152005-07-12 13:59:01 -0700700 case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 ir_codes = videomate_tv_pvr_codes;
702 mask_keycode = 0x00003F;
703 mask_keyup = 0x400000;
704 polling = 50; // ms
705 break;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800706 case SAA7134_BOARD_VIDEOMATE_DVBT_300:
707 case SAA7134_BOARD_VIDEOMATE_DVBT_200:
Nickolay V. Shmyrevfea095f2005-11-08 21:36:47 -0800708 ir_codes = videomate_tv_pvr_codes;
709 mask_keycode = 0x003F00;
710 mask_keyup = 0x040000;
711 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712 }
713 if (NULL == ir_codes) {
714 printk("%s: Oops: IR config error [card=%d]\n",
715 dev->name, dev->board);
716 return -ENODEV;
717 }
718
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500719 ir = kzalloc(sizeof(*ir), GFP_KERNEL);
720 input_dev = input_allocate_device();
721 if (!ir || !input_dev) {
722 kfree(ir);
723 input_free_device(input_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 return -ENOMEM;
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500725 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726
Dmitry Torokhovd271d1c2005-11-20 00:56:54 -0500727 ir->dev = input_dev;
728
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729 /* init hardware-specific stuff */
730 ir->mask_keycode = mask_keycode;
731 ir->mask_keydown = mask_keydown;
732 ir->mask_keyup = mask_keyup;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800733 ir->polling = polling;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734
735 /* init input device */
736 snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)",
737 saa7134_boards[dev->board].name);
738 snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
739 pci_name(dev->pci));
740
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500741 ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
742 input_dev->name = ir->name;
743 input_dev->phys = ir->phys;
744 input_dev->id.bustype = BUS_PCI;
745 input_dev->id.version = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 if (dev->pci->subsystem_vendor) {
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500747 input_dev->id.vendor = dev->pci->subsystem_vendor;
748 input_dev->id.product = dev->pci->subsystem_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 } else {
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500750 input_dev->id.vendor = dev->pci->vendor;
751 input_dev->id.product = dev->pci->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 }
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500753 input_dev->cdev.dev = &dev->pci->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754
755 /* all done */
756 dev->remote = ir;
757 if (ir->polling) {
758 init_timer(&ir->timer);
759 ir->timer.function = saa7134_input_timer;
760 ir->timer.data = (unsigned long)dev;
761 ir->timer.expires = jiffies + HZ;
762 add_timer(&ir->timer);
763 }
764
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500765 input_register_device(ir->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 return 0;
767}
768
769void saa7134_input_fini(struct saa7134_dev *dev)
770{
771 if (NULL == dev->remote)
772 return;
773
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 if (dev->remote->polling)
775 del_timer_sync(&dev->remote->timer);
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500776 input_unregister_device(dev->remote->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 kfree(dev->remote);
778 dev->remote = NULL;
779}
780
Ricardo Cerqueiraac9cd972005-11-08 21:37:56 -0800781void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir)
782{
783 if (disable_ir) {
Ricardo Cerqueiracb2444d2005-11-08 21:38:47 -0800784 dprintk("Found supported i2c remote, but IR has been disabled\n");
Ricardo Cerqueiraac9cd972005-11-08 21:37:56 -0800785 ir->get_key=NULL;
786 return;
787 }
788
789 switch (dev->board) {
790 case SAA7134_BOARD_PINNACLE_PCTV_110i:
791 snprintf(ir->c.name, sizeof(ir->c.name), "Pinnacle PCTV");
792 ir->get_key = get_key_pinnacle;
793 ir->ir_codes = ir_codes_pinnacle;
794 break;
795 case SAA7134_BOARD_UPMOST_PURPLE_TV:
796 snprintf(ir->c.name, sizeof(ir->c.name), "Purple TV");
797 ir->get_key = get_key_purpletv;
798 ir->ir_codes = ir_codes_purpletv;
799 break;
800 default:
801 dprintk("Shouldn't get here: Unknown board %x for I2C IR?\n",dev->board);
802 break;
803 }
804
805}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806/* ----------------------------------------------------------------------
807 * Local variables:
808 * c-basic-offset: 8
809 * End:
810 */