blob: 7175abbd2f8c58ff32aa7e2c46fe79c57a79135e [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
59 [ 14 ] = KEY_TUNER, // Air/Cable
60 [ 17 ] = KEY_VIDEO, // Video
61 [ 21 ] = KEY_AUDIO, // Audio
62 [ 0 ] = KEY_POWER, // Pover
63 [ 2 ] = KEY_ZOOM, // Fullscreen
64 [ 27 ] = KEY_MUTE, // Mute
65 [ 20 ] = KEY_VOLUMEUP,
66 [ 23 ] = KEY_VOLUMEDOWN,
67 [ 18 ] = KEY_CHANNELUP, // Channel +
68 [ 19 ] = KEY_CHANNELDOWN, // Channel -
69 [ 6 ] = KEY_AGAIN, // Recal
70 [ 16 ] = KEY_KPENTER, // Enter
71
Linus Torvalds1da177e2005-04-16 15:20:36 -070072 [ 26 ] = KEY_F22, // Stereo
73 [ 24 ] = KEY_EDIT, // AV Source
Linus Torvalds1da177e2005-04-16 15:20:36 -070074};
75
76static 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
546 if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) ||
547 (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) {
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500548 ir_input_keydown(ir->dev, &ir->ir, data, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 } else {
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500550 ir_input_nokey(ir->dev, &ir->ir);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 }
552 return 0;
553}
554
Ricardo Cerqueiraac9cd972005-11-08 21:37:56 -0800555/* --------------------- Chip specific I2C key builders ----------------- */
556
557static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
558{
559 unsigned char b;
560
561 /* poll IR chip */
562 if (1 != i2c_master_recv(&ir->c,&b,1)) {
563 i2cdprintk("read error\n");
564 return -EIO;
565 }
566
567 /* no button press */
568 if (b==0)
569 return 0;
570
571 /* repeating */
572 if (b & 0x80)
573 return 1;
574
575 *ir_key = b;
576 *ir_raw = b;
577 return 1;
578}
579
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580void saa7134_input_irq(struct saa7134_dev *dev)
581{
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800582 struct saa7134_ir *ir = dev->remote;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800584 if (!ir->polling)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585 build_key(dev);
586}
587
588static void saa7134_input_timer(unsigned long data)
589{
590 struct saa7134_dev *dev = (struct saa7134_dev*)data;
591 struct saa7134_ir *ir = dev->remote;
592 unsigned long timeout;
593
594 build_key(dev);
595 timeout = jiffies + (ir->polling * HZ / 1000);
596 mod_timer(&ir->timer, timeout);
597}
598
599int saa7134_input_init1(struct saa7134_dev *dev)
600{
601 struct saa7134_ir *ir;
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500602 struct input_dev *input_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603 IR_KEYTAB_TYPE *ir_codes = NULL;
604 u32 mask_keycode = 0;
605 u32 mask_keydown = 0;
606 u32 mask_keyup = 0;
607 int polling = 0;
608 int ir_type = IR_TYPE_OTHER;
609
Ricardo Cerqueiracb2444d2005-11-08 21:38:47 -0800610 if (dev->has_remote != SAA7134_REMOTE_GPIO)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 return -ENODEV;
612 if (disable_ir)
613 return -ENODEV;
614
615 /* detect & configure */
616 switch (dev->board) {
617 case SAA7134_BOARD_FLYVIDEO2000:
618 case SAA7134_BOARD_FLYVIDEO3000:
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800619 case SAA7134_BOARD_FLYTVPLATINUM_FM:
Arnaud Patard6af90ab2005-11-08 21:36:55 -0800620 case SAA7134_BOARD_FLYTVPLATINUM_MINI2:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 ir_codes = flyvideo_codes;
622 mask_keycode = 0xEC00000;
623 mask_keydown = 0x0040000;
624 break;
625 case SAA7134_BOARD_CINERGY400:
626 case SAA7134_BOARD_CINERGY600:
627 case SAA7134_BOARD_CINERGY600_MK3:
628 ir_codes = cinergy_codes;
629 mask_keycode = 0x00003f;
630 mask_keyup = 0x040000;
631 break;
632 case SAA7134_BOARD_ECS_TVP3XP:
633 case SAA7134_BOARD_ECS_TVP3XP_4CB5:
Mauro Carvalho Chehab330a1152005-07-12 13:59:01 -0700634 ir_codes = eztv_codes;
635 mask_keycode = 0x00017c;
636 mask_keyup = 0x000002;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 polling = 50; // ms
Mauro Carvalho Chehab330a1152005-07-12 13:59:01 -0700638 break;
639 case SAA7134_BOARD_KWORLD_XPERT:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 case SAA7134_BOARD_AVACSSMARTTV:
Mauro Carvalho Chehab330a1152005-07-12 13:59:01 -0700641 ir_codes = avacssmart_codes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642 mask_keycode = 0x00001F;
643 mask_keyup = 0x000020;
644 polling = 50; // ms
645 break;
646 case SAA7134_BOARD_MD2819:
Mauro Carvalho Chehabac19ecc2005-06-23 22:05:09 -0700647 case SAA7134_BOARD_KWORLD_VSTREAM_XPERT:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 case SAA7134_BOARD_AVERMEDIA_305:
649 case SAA7134_BOARD_AVERMEDIA_307:
Mauro Carvalho Chehabac19ecc2005-06-23 22:05:09 -0700650 case SAA7134_BOARD_AVERMEDIA_STUDIO_305:
651 case SAA7134_BOARD_AVERMEDIA_STUDIO_307:
652 case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 ir_codes = md2819_codes;
654 mask_keycode = 0x0007C8;
655 mask_keydown = 0x000010;
656 polling = 50; // ms
657 /* Set GPIO pin2 to high to enable the IR controller */
658 saa_setb(SAA7134_GPIO_GPMODE0, 0x4);
659 saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4);
660 break;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800661 case SAA7134_BOARD_KWORLD_TERMINATOR:
James R. Webbdc2286c2005-11-08 21:37:00 -0800662 ir_codes = avacssmart_codes;
663 mask_keycode = 0x00001f;
664 mask_keyup = 0x000060;
665 polling = 50; // ms
666 break;
Mauro Carvalho Chehabac19ecc2005-06-23 22:05:09 -0700667 case SAA7134_BOARD_MANLI_MTV001:
668 case SAA7134_BOARD_MANLI_MTV002:
Nickolay V. Shmyreva8ff4172005-11-08 21:36:16 -0800669 case SAA7134_BOARD_BEHOLD_409FM:
Mauro Carvalho Chehabac19ecc2005-06-23 22:05:09 -0700670 ir_codes = manli_codes;
671 mask_keycode = 0x001f00;
672 mask_keyup = 0x004000;
Mauro Carvalho Chehabac19ecc2005-06-23 22:05:09 -0700673 polling = 50; // ms
674 break;
Ricardo Cerqueira17ce1ff2005-11-08 21:38:47 -0800675 case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS:
676 ir_codes = pctv_sedna_codes;
Pavel Mihaylovc3d93192005-11-08 21:38:43 -0800677 mask_keycode = 0x001f00;
678 mask_keyup = 0x004000;
679 polling = 50; // ms
680 break;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800681 case SAA7134_BOARD_GOTVIEW_7135:
Nickolay V. Shmyrev6b961442005-11-08 21:36:22 -0800682 ir_codes = gotview7135_codes;
683 mask_keycode = 0x0003EC;
684 mask_keyup = 0x008000;
685 mask_keydown = 0x000010;
686 polling = 50; // ms
687 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688 case SAA7134_BOARD_VIDEOMATE_TV_PVR:
Nickolay V. Shmyrev2a9a9a82006-01-09 15:25:33 -0200689 case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS:
Mauro Carvalho Chehab330a1152005-07-12 13:59:01 -0700690 case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 ir_codes = videomate_tv_pvr_codes;
692 mask_keycode = 0x00003F;
693 mask_keyup = 0x400000;
694 polling = 50; // ms
695 break;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800696 case SAA7134_BOARD_VIDEOMATE_DVBT_300:
697 case SAA7134_BOARD_VIDEOMATE_DVBT_200:
Nickolay V. Shmyrevfea095f2005-11-08 21:36:47 -0800698 ir_codes = videomate_tv_pvr_codes;
699 mask_keycode = 0x003F00;
700 mask_keyup = 0x040000;
701 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 }
703 if (NULL == ir_codes) {
704 printk("%s: Oops: IR config error [card=%d]\n",
705 dev->name, dev->board);
706 return -ENODEV;
707 }
708
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500709 ir = kzalloc(sizeof(*ir), GFP_KERNEL);
710 input_dev = input_allocate_device();
711 if (!ir || !input_dev) {
712 kfree(ir);
713 input_free_device(input_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714 return -ENOMEM;
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500715 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716
Dmitry Torokhovd271d1c2005-11-20 00:56:54 -0500717 ir->dev = input_dev;
718
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 /* init hardware-specific stuff */
720 ir->mask_keycode = mask_keycode;
721 ir->mask_keydown = mask_keydown;
722 ir->mask_keyup = mask_keyup;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800723 ir->polling = polling;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724
725 /* init input device */
726 snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)",
727 saa7134_boards[dev->board].name);
728 snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
729 pci_name(dev->pci));
730
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500731 ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
732 input_dev->name = ir->name;
733 input_dev->phys = ir->phys;
734 input_dev->id.bustype = BUS_PCI;
735 input_dev->id.version = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 if (dev->pci->subsystem_vendor) {
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500737 input_dev->id.vendor = dev->pci->subsystem_vendor;
738 input_dev->id.product = dev->pci->subsystem_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 } else {
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500740 input_dev->id.vendor = dev->pci->vendor;
741 input_dev->id.product = dev->pci->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 }
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500743 input_dev->cdev.dev = &dev->pci->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744
745 /* all done */
746 dev->remote = ir;
747 if (ir->polling) {
748 init_timer(&ir->timer);
749 ir->timer.function = saa7134_input_timer;
750 ir->timer.data = (unsigned long)dev;
751 ir->timer.expires = jiffies + HZ;
752 add_timer(&ir->timer);
753 }
754
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500755 input_register_device(ir->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 return 0;
757}
758
759void saa7134_input_fini(struct saa7134_dev *dev)
760{
761 if (NULL == dev->remote)
762 return;
763
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 if (dev->remote->polling)
765 del_timer_sync(&dev->remote->timer);
Dmitry Torokhovb7df3912005-09-15 02:01:53 -0500766 input_unregister_device(dev->remote->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767 kfree(dev->remote);
768 dev->remote = NULL;
769}
770
Ricardo Cerqueiraac9cd972005-11-08 21:37:56 -0800771void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir)
772{
773 if (disable_ir) {
Ricardo Cerqueiracb2444d2005-11-08 21:38:47 -0800774 dprintk("Found supported i2c remote, but IR has been disabled\n");
Ricardo Cerqueiraac9cd972005-11-08 21:37:56 -0800775 ir->get_key=NULL;
776 return;
777 }
778
779 switch (dev->board) {
780 case SAA7134_BOARD_PINNACLE_PCTV_110i:
781 snprintf(ir->c.name, sizeof(ir->c.name), "Pinnacle PCTV");
782 ir->get_key = get_key_pinnacle;
783 ir->ir_codes = ir_codes_pinnacle;
784 break;
785 case SAA7134_BOARD_UPMOST_PURPLE_TV:
786 snprintf(ir->c.name, sizeof(ir->c.name), "Purple TV");
787 ir->get_key = get_key_purpletv;
788 ir->ir_codes = ir_codes_purpletv;
789 break;
790 default:
791 dprintk("Shouldn't get here: Unknown board %x for I2C IR?\n",dev->board);
792 break;
793 }
794
795}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796/* ----------------------------------------------------------------------
797 * Local variables:
798 * c-basic-offset: 8
799 * End:
800 */