cx88-input.c 14.1 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
/*
 *
 * Device driver for GPIO attached remote control interfaces
 * on Conexant 2388x based TV/DVB cards.
 *
 * Copyright (c) 2003 Pavel Machek
 * Copyright (c) 2004 Gerd Knorr
 * Copyright (c) 2004 Chris Pascoe
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#include <linux/init.h>
#include <linux/delay.h>
#include <linux/input.h>
#include <linux/pci.h>
#include <linux/module.h>
#include <linux/moduleparam.h>

#include <media/ir-common.h>

#include "cx88.h"

/* ---------------------------------------------------------------------- */

/* DigitalNow DNTV Live DVB-T Remote */
static IR_KEYTAB_TYPE ir_codes_dntv_live_dvb_t[IR_KEYTAB_SIZE] = {
M
Mauro Carvalho Chehab 已提交
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
	[0x00] = KEY_ESC,		/* 'go up a level?' */
	/* Keys 0 to 9 */
	[0x0a] = KEY_KP0,
	[0x01] = KEY_KP1,
	[0x02] = KEY_KP2,
	[0x03] = KEY_KP3,
	[0x04] = KEY_KP4,
	[0x05] = KEY_KP5,
	[0x06] = KEY_KP6,
	[0x07] = KEY_KP7,
	[0x08] = KEY_KP8,
	[0x09] = KEY_KP9,

	[0x0b] = KEY_TUNER,		/* tv/fm */
	[0x0c] = KEY_SEARCH,		/* scan */
	[0x0d] = KEY_STOP,
	[0x0e] = KEY_PAUSE,
	[0x0f] = KEY_LIST,		/* source */

	[0x10] = KEY_MUTE,
	[0x11] = KEY_REWIND,		/* backward << */
	[0x12] = KEY_POWER,
	[0x13] = KEY_S,			/* snap */
	[0x14] = KEY_AUDIO,		/* stereo */
	[0x15] = KEY_CLEAR,		/* reset */
	[0x16] = KEY_PLAY,
	[0x17] = KEY_ENTER,
	[0x18] = KEY_ZOOM,		/* full screen */
	[0x19] = KEY_FASTFORWARD,	/* forward >> */
	[0x1a] = KEY_CHANNELUP,
	[0x1b] = KEY_VOLUMEUP,
	[0x1c] = KEY_INFO,		/* preview */
	[0x1d] = KEY_RECORD,		/* record */
	[0x1e] = KEY_CHANNELDOWN,
	[0x1f] = KEY_VOLUMEDOWN,
L
Linus Torvalds 已提交
75 76 77 78 79 80
};

/* ---------------------------------------------------------------------- */

/* IO-DATA BCTV7E Remote */
static IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE] = {
M
Mauro Carvalho Chehab 已提交
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
	[0x40] = KEY_TV,
	[0x20] = KEY_RADIO,		/* FM */
	[0x60] = KEY_EPG,
	[0x00] = KEY_POWER,

	/* Keys 0 to 9 */
	[0x44] = KEY_KP0,		/* 10 */
	[0x50] = KEY_KP1,
	[0x30] = KEY_KP2,
	[0x70] = KEY_KP3,
	[0x48] = KEY_KP4,
	[0x28] = KEY_KP5,
	[0x68] = KEY_KP6,
	[0x58] = KEY_KP7,
	[0x38] = KEY_KP8,
	[0x78] = KEY_KP9,

	[0x10] = KEY_L,			/* Live */
	[0x08] = KEY_T,			/* Time Shift */

	[0x18] = KEY_PLAYPAUSE,		/* Play */

	[0x24] = KEY_ENTER,		/* 11 */
	[0x64] = KEY_ESC,		/* 12 */
	[0x04] = KEY_M,			/* Multi */

	[0x54] = KEY_VIDEO,
	[0x34] = KEY_CHANNELUP,
	[0x74] = KEY_VOLUMEUP,
	[0x14] = KEY_MUTE,

	[0x4c] = KEY_S,			/* SVIDEO */
	[0x2c] = KEY_CHANNELDOWN,
	[0x6c] = KEY_VOLUMEDOWN,
	[0x0c] = KEY_ZOOM,

	[0x5c] = KEY_PAUSE,
	[0x3c] = KEY_C,			/* || (red) */
	[0x7c] = KEY_RECORD,		/* recording */
	[0x1c] = KEY_STOP,

	[0x41] = KEY_REWIND,		/* backward << */
	[0x21] = KEY_PLAY,
	[0x61] = KEY_FASTFORWARD,	/* forward >> */
	[0x01] = KEY_NEXT,		/* skip >| */
L
Linus Torvalds 已提交
126 127 128 129
};

/* ---------------------------------------------------------------------- */

M
Mauro Carvalho Chehab 已提交
130 131
/* ADS Tech Instant TV DVB-T PCI Remote */
static IR_KEYTAB_TYPE ir_codes_adstech_dvb_t_pci[IR_KEYTAB_SIZE] = {
M
Mauro Carvalho Chehab 已提交
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
	/* Keys 0 to 9 */
	[0x4d] = KEY_0,
	[0x57] = KEY_1,
	[0x4f] = KEY_2,
	[0x53] = KEY_3,
	[0x56] = KEY_4,
	[0x4e] = KEY_5,
	[0x5e] = KEY_6,
	[0x54] = KEY_7,
	[0x4c] = KEY_8,
	[0x5c] = KEY_9,

	[0x5b] = KEY_POWER,
	[0x5f] = KEY_MUTE,
	[0x55] = KEY_GOTO,
	[0x5d] = KEY_SEARCH,
	[0x17] = KEY_EPG,		/* Guide */
	[0x1f] = KEY_MENU,
	[0x0f] = KEY_UP,
	[0x46] = KEY_DOWN,
	[0x16] = KEY_LEFT,
	[0x1e] = KEY_RIGHT,
	[0x0e] = KEY_SELECT,		/* Enter */
	[0x5a] = KEY_INFO,
	[0x52] = KEY_EXIT,
	[0x59] = KEY_PREVIOUS,
	[0x51] = KEY_NEXT,
	[0x58] = KEY_REWIND,
	[0x50] = KEY_FORWARD,
	[0x44] = KEY_PLAYPAUSE,
	[0x07] = KEY_STOP,
	[0x1b] = KEY_RECORD,
	[0x13] = KEY_TUNER,		/* Live */
	[0x0a] = KEY_A,
	[0x12] = KEY_B,
	[0x03] = KEY_PROG1,		/* 1 */
	[0x01] = KEY_PROG2,		/* 2 */
	[0x00] = KEY_PROG3,		/* 3 */
	[0x06] = KEY_DVD,
	[0x48] = KEY_AUX,		/* Photo */
	[0x40] = KEY_VIDEO,
	[0x19] = KEY_AUDIO,		/* Music */
	[0x0b] = KEY_CHANNELUP,
	[0x08] = KEY_CHANNELDOWN,
	[0x15] = KEY_VOLUMEUP,
	[0x1c] = KEY_VOLUMEDOWN,
M
Mauro Carvalho Chehab 已提交
178 179 180 181 182 183
};

/* ---------------------------------------------------------------------- */

/* MSI TV@nywhere remote */
static IR_KEYTAB_TYPE ir_codes_msi_tvanywhere[IR_KEYTAB_SIZE] = {
M
Mauro Carvalho Chehab 已提交
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
	/* Keys 0 to 9 */
	[0x00] = KEY_0,
	[0x01] = KEY_1,
	[0x02] = KEY_2,
	[0x03] = KEY_3,
	[0x04] = KEY_4,
	[0x05] = KEY_5,
	[0x06] = KEY_6,
	[0x07] = KEY_7,
	[0x08] = KEY_8,
	[0x09] = KEY_9,

	[0x0c] = KEY_MUTE,
	[0x0f] = KEY_SCREEN,		/* Full Screen */
	[0x10] = KEY_F,			/* Funtion */
	[0x11] = KEY_T,			/* Time shift */
	[0x12] = KEY_POWER,
	[0x13] = KEY_MEDIA,		/* MTS */
	[0x14] = KEY_SLOW,
	[0x16] = KEY_REWIND,		/* backward << */
	[0x17] = KEY_ENTER,		/* Return */
	[0x18] = KEY_FASTFORWARD,	/* forward >> */
	[0x1a] = KEY_CHANNELUP,
	[0x1b] = KEY_VOLUMEUP,
	[0x1e] = KEY_CHANNELDOWN,
	[0x1f] = KEY_VOLUMEDOWN,
M
Mauro Carvalho Chehab 已提交
210 211 212 213
};

/* ---------------------------------------------------------------------- */

214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
/* Cinergy 1400 DVB-T */
static IR_KEYTAB_TYPE ir_codes_cinergy_1400[IR_KEYTAB_SIZE] = {
	[0x01] = KEY_POWER,
	[0x02] = KEY_1,
	[0x03] = KEY_2,
	[0x04] = KEY_3,
	[0x05] = KEY_4,
	[0x06] = KEY_5,
	[0x07] = KEY_6,
	[0x08] = KEY_7,
	[0x09] = KEY_8,
	[0x0a] = KEY_9,
	[0x0c] = KEY_0,

	[0x0b] = KEY_VIDEO,
	[0x0d] = KEY_REFRESH,
	[0x0e] = KEY_SELECT,
	[0x0f] = KEY_EPG,
	[0x10] = KEY_UP,
	[0x11] = KEY_LEFT,
	[0x12] = KEY_OK,
	[0x13] = KEY_RIGHT,
	[0x14] = KEY_DOWN,
	[0x15] = KEY_TEXT,
	[0x16] = KEY_INFO,

	[0x17] = KEY_RED,
	[0x18] = KEY_GREEN,
	[0x19] = KEY_YELLOW,
	[0x1a] = KEY_BLUE,

	[0x1b] = KEY_CHANNELUP,
	[0x1c] = KEY_VOLUMEUP,
	[0x1d] = KEY_MUTE,
	[0x1e] = KEY_VOLUMEDOWN,
	[0x1f] = KEY_CHANNELDOWN,

	[0x40] = KEY_PAUSE,
	[0x4c] = KEY_PLAY,
	[0x58] = KEY_RECORD,
	[0x54] = KEY_PREVIOUS,
	[0x48] = KEY_STOP,
	[0x5c] = KEY_NEXT,
};

/* ---------------------------------------------------------------------- */

L
Linus Torvalds 已提交
261
struct cx88_IR {
M
Mauro Carvalho Chehab 已提交
262
	struct cx88_core *core;
263
	struct input_dev *input;
M
Mauro Carvalho Chehab 已提交
264 265 266
	struct ir_input_state ir;
	char name[32];
	char phys[32];
L
Linus Torvalds 已提交
267 268

	/* sample from gpio pin 16 */
M
Mauro Carvalho Chehab 已提交
269 270 271 272
	int sampling;
	u32 samples[16];
	int scount;
	unsigned long release;
L
Linus Torvalds 已提交
273 274

	/* poll external decoder */
M
Mauro Carvalho Chehab 已提交
275 276 277 278 279 280 281 282
	int polling;
	struct work_struct work;
	struct timer_list timer;
	u32 gpio_addr;
	u32 last_gpio;
	u32 mask_keycode;
	u32 mask_keydown;
	u32 mask_keyup;
L
Linus Torvalds 已提交
283 284 285
};

static int ir_debug = 0;
M
Mauro Carvalho Chehab 已提交
286
module_param(ir_debug, int, 0644);	/* debug level [IR] */
L
Linus Torvalds 已提交
287 288 289
MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");

#define ir_dprintk(fmt, arg...)	if (ir_debug) \
290
	printk(KERN_DEBUG "%s IR: " fmt , ir->core->name , ##arg)
L
Linus Torvalds 已提交
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309

/* ---------------------------------------------------------------------- */

static void cx88_ir_handle_key(struct cx88_IR *ir)
{
	struct cx88_core *core = ir->core;
	u32 gpio, data;

	/* read gpio value */
	gpio = cx_read(ir->gpio_addr);
	if (ir->polling) {
		if (ir->last_gpio == gpio)
			return;
		ir->last_gpio = gpio;
	}

	/* extract data */
	data = ir_extract_bits(gpio, ir->mask_keycode);
	ir_dprintk("irq gpio=0x%x code=%d | %s%s%s\n",
M
Mauro Carvalho Chehab 已提交
310 311 312 313
		   gpio, data,
		   ir->polling ? "poll" : "irq",
		   (gpio & ir->mask_keydown) ? " down" : "",
		   (gpio & ir->mask_keyup) ? " up" : "");
L
Linus Torvalds 已提交
314 315 316 317

	if (ir->mask_keydown) {
		/* bit set on keydown */
		if (gpio & ir->mask_keydown) {
318
			ir_input_keydown(ir->input, &ir->ir, data, data);
L
Linus Torvalds 已提交
319
		} else {
320
			ir_input_nokey(ir->input, &ir->ir);
L
Linus Torvalds 已提交
321 322 323 324 325
		}

	} else if (ir->mask_keyup) {
		/* bit cleared on keydown */
		if (0 == (gpio & ir->mask_keyup)) {
326
			ir_input_keydown(ir->input, &ir->ir, data, data);
L
Linus Torvalds 已提交
327
		} else {
328
			ir_input_nokey(ir->input, &ir->ir);
L
Linus Torvalds 已提交
329 330 331 332
		}

	} else {
		/* can't distinguish keydown/up :-/ */
333 334
		ir_input_keydown(ir->input, &ir->ir, data, data);
		ir_input_nokey(ir->input, &ir->ir);
L
Linus Torvalds 已提交
335 336 337 338 339
	}
}

static void ir_timer(unsigned long data)
{
M
Mauro Carvalho Chehab 已提交
340
	struct cx88_IR *ir = (struct cx88_IR *)data;
L
Linus Torvalds 已提交
341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359

	schedule_work(&ir->work);
}

static void cx88_ir_work(void *data)
{
	struct cx88_IR *ir = data;
	unsigned long timeout;

	cx88_ir_handle_key(ir);
	timeout = jiffies + (ir->polling * HZ / 1000);
	mod_timer(&ir->timer, timeout);
}

/* ---------------------------------------------------------------------- */

int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
{
	struct cx88_IR *ir;
360
	struct input_dev *input_dev;
L
Linus Torvalds 已提交
361 362 363
	IR_KEYTAB_TYPE *ir_codes = NULL;
	int ir_type = IR_TYPE_OTHER;

364 365 366 367 368
	ir = kzalloc(sizeof(*ir), GFP_KERNEL);
	input_dev = input_allocate_device();
	if (!ir || !input_dev) {
		kfree(ir);
		input_free_device(input_dev);
L
Linus Torvalds 已提交
369
		return -ENOMEM;
370 371 372
	}

	ir->input = input_dev;
L
Linus Torvalds 已提交
373 374 375 376

	/* detect & configure */
	switch (core->board) {
	case CX88_BOARD_DNTV_LIVE_DVB_T:
377
	case CX88_BOARD_KWORLD_DVB_T:
M
Mauro Carvalho Chehab 已提交
378 379
		ir_codes = ir_codes_dntv_live_dvb_t;
		ir->gpio_addr = MO_GP1_IO;
L
Linus Torvalds 已提交
380
		ir->mask_keycode = 0x1f;
M
Mauro Carvalho Chehab 已提交
381 382
		ir->mask_keyup = 0x60;
		ir->polling = 50; /* ms */
L
Linus Torvalds 已提交
383
		break;
384 385 386 387 388
	case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
		ir_codes = ir_codes_cinergy_1400;
		ir_type = IR_TYPE_PD;
		ir->sampling = 1;
		break;
L
Linus Torvalds 已提交
389 390
	case CX88_BOARD_HAUPPAUGE:
	case CX88_BOARD_HAUPPAUGE_DVB_T1:
M
Mauro Carvalho Chehab 已提交
391 392 393
		ir_codes = ir_codes_hauppauge_new;
		ir_type = IR_TYPE_RC5;
		ir->sampling = 1;
L
Linus Torvalds 已提交
394 395
		break;
	case CX88_BOARD_WINFAST2000XP_EXPERT:
M
Mauro Carvalho Chehab 已提交
396 397
		ir_codes = ir_codes_winfast;
		ir->gpio_addr = MO_GP0_IO;
L
Linus Torvalds 已提交
398
		ir->mask_keycode = 0x8f8;
M
Mauro Carvalho Chehab 已提交
399 400
		ir->mask_keyup = 0x100;
		ir->polling = 1; /* ms */
L
Linus Torvalds 已提交
401 402
		break;
	case CX88_BOARD_IODATA_GVBCTV7E:
M
Mauro Carvalho Chehab 已提交
403 404
		ir_codes = ir_codes_iodata_bctv7e;
		ir->gpio_addr = MO_GP0_IO;
L
Linus Torvalds 已提交
405 406
		ir->mask_keycode = 0xfd;
		ir->mask_keydown = 0x02;
M
Mauro Carvalho Chehab 已提交
407
		ir->polling = 5; /* ms */
L
Linus Torvalds 已提交
408
		break;
409
	case CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO:
M
Mauro Carvalho Chehab 已提交
410 411
		ir_codes = ir_codes_pixelview;
		ir->gpio_addr = MO_GP1_IO;
412
		ir->mask_keycode = 0x1f;
M
Mauro Carvalho Chehab 已提交
413 414
		ir->mask_keyup = 0x80;
		ir->polling = 1; /* ms */
415
		break;
M
Mauro Carvalho Chehab 已提交
416
	case CX88_BOARD_ADSTECH_DVB_T_PCI:
M
Mauro Carvalho Chehab 已提交
417 418
		ir_codes = ir_codes_adstech_dvb_t_pci;
		ir->gpio_addr = MO_GP1_IO;
M
Mauro Carvalho Chehab 已提交
419
		ir->mask_keycode = 0xbf;
M
Mauro Carvalho Chehab 已提交
420 421 422 423 424 425 426 427 428
		ir->mask_keyup = 0x40;
		ir->polling = 50; /* ms */
		break;
	case CX88_BOARD_MSI_TVANYWHERE_MASTER:
		ir_codes = ir_codes_msi_tvanywhere;
		ir->gpio_addr = MO_GP1_IO;
		ir->mask_keycode = 0x1f;
		ir->mask_keyup = 0x40;
		ir->polling = 1; /* ms */
M
Mauro Carvalho Chehab 已提交
429
		break;
L
Linus Torvalds 已提交
430
	}
431

L
Linus Torvalds 已提交
432 433
	if (NULL == ir_codes) {
		kfree(ir);
434
		input_free_device(input_dev);
L
Linus Torvalds 已提交
435 436 437 438 439 440
		return -ENODEV;
	}

	/* init input device */
	snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)",
		 cx88_boards[core->board].name);
M
Mauro Carvalho Chehab 已提交
441
	snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci));
L
Linus Torvalds 已提交
442

443 444 445 446 447
	ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
	input_dev->name = ir->name;
	input_dev->phys = ir->phys;
	input_dev->id.bustype = BUS_PCI;
	input_dev->id.version = 1;
L
Linus Torvalds 已提交
448
	if (pci->subsystem_vendor) {
449 450
		input_dev->id.vendor = pci->subsystem_vendor;
		input_dev->id.product = pci->subsystem_device;
L
Linus Torvalds 已提交
451
	} else {
452 453
		input_dev->id.vendor = pci->vendor;
		input_dev->id.product = pci->device;
L
Linus Torvalds 已提交
454
	}
455
	input_dev->cdev.dev = &pci->dev;
L
Linus Torvalds 已提交
456 457 458 459 460 461 462 463
	/* record handles to ourself */
	ir->core = core;
	core->ir = ir;

	if (ir->polling) {
		INIT_WORK(&ir->work, cx88_ir_work, ir);
		init_timer(&ir->timer);
		ir->timer.function = ir_timer;
M
Mauro Carvalho Chehab 已提交
464
		ir->timer.data = (unsigned long)ir;
L
Linus Torvalds 已提交
465 466 467
		schedule_work(&ir->work);
	}
	if (ir->sampling) {
M
Mauro Carvalho Chehab 已提交
468 469 470
		core->pci_irqmask |= (1 << 18);	/* IR_SMP_INT */
		cx_write(MO_DDS_IO, 0xa80a80);	/* 4 kHz sample rate */
		cx_write(MO_DDSCFG_IO, 0x5);	/* enable */
L
Linus Torvalds 已提交
471 472 473
	}

	/* all done */
474
	input_register_device(ir->input);
L
Linus Torvalds 已提交
475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491

	return 0;
}

int cx88_ir_fini(struct cx88_core *core)
{
	struct cx88_IR *ir = core->ir;

	/* skip detach on non attached boards */
	if (NULL == ir)
		return 0;

	if (ir->polling) {
		del_timer(&ir->timer);
		flush_scheduled_work();
	}

492
	input_unregister_device(ir->input);
L
Linus Torvalds 已提交
493 494 495 496 497 498 499 500 501 502 503 504
	kfree(ir);

	/* done */
	core->ir = NULL;
	return 0;
}

/* ---------------------------------------------------------------------- */

void cx88_ir_irq(struct cx88_core *core)
{
	struct cx88_IR *ir = core->ir;
505
	u32 samples, ircode;
L
Linus Torvalds 已提交
506 507 508 509 510 511 512 513
	int i;

	if (NULL == ir)
		return;
	if (!ir->sampling)
		return;

	samples = cx_read(MO_SAMPLE_IO);
M
Mauro Carvalho Chehab 已提交
514
	if (0 != samples && 0xffffffff != samples) {
L
Linus Torvalds 已提交
515 516 517 518 519 520 521
		/* record sample data */
		if (ir->scount < ARRAY_SIZE(ir->samples))
			ir->samples[ir->scount++] = samples;
		return;
	}
	if (!ir->scount) {
		/* nothing to sample */
M
Mauro Carvalho Chehab 已提交
522
		if (ir->ir.keypressed && time_after(jiffies, ir->release))
523
			ir_input_nokey(ir->input, &ir->ir);
L
Linus Torvalds 已提交
524 525 526 527 528 529 530 531 532
		return;
	}

	/* have a complete sample */
	if (ir->scount < ARRAY_SIZE(ir->samples))
		ir->samples[ir->scount++] = samples;
	for (i = 0; i < ir->scount; i++)
		ir->samples[i] = ~ir->samples[i];
	if (ir_debug)
M
Mauro Carvalho Chehab 已提交
533
		ir_dump_samples(ir->samples, ir->scount);
L
Linus Torvalds 已提交
534 535 536

	/* decode it */
	switch (core->board) {
537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554
	case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
		ircode = ir_decode_pulsedistance(ir->samples, ir->scount, 1, 4);

		if (ircode == 0xffffffff) { /* decoding error */
			ir_dprintk("pulse distance decoding error\n");
			break;
		}

		ir_dprintk("pulse distance decoded: %x\n", ircode);

		if (ircode == 0) { /* key still pressed */
			ir_dprintk("pulse distance decoded repeat code\n");
			ir->release = jiffies + msecs_to_jiffies(120);
			break;
		}

		if ((ircode & 0xffff) != 0xeb04) { /* wrong address */
			ir_dprintk("pulse distance decoded wrong address\n");
555
			break;
556 557 558 559 560 561 562 563 564
		}

		if (((~ircode >> 24) & 0xff) != ((ircode >> 16) & 0xff)) { /* wrong checksum */
			ir_dprintk("pulse distance decoded wrong check sum\n");
			break;
		}

		ir_dprintk("Key Code: %x\n", (ircode >> 16) & 0x7f);

565
		ir_input_keydown(ir->input, &ir->ir, (ircode >> 16) & 0x7f, (ircode >> 16) & 0xff);
566 567
		ir->release = jiffies + msecs_to_jiffies(120);
		break;
L
Linus Torvalds 已提交
568 569
	case CX88_BOARD_HAUPPAUGE:
	case CX88_BOARD_HAUPPAUGE_DVB_T1:
570 571 572
		ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7);
		ir_dprintk("biphase decoded: %x\n", ircode);
		if ((ircode & 0xfffff000) != 0x3000)
L
Linus Torvalds 已提交
573
			break;
574
		ir_input_keydown(ir->input, &ir->ir, ircode & 0x3f, ircode);
L
Linus Torvalds 已提交
575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592
		ir->release = jiffies + msecs_to_jiffies(120);
		break;
	}

	ir->scount = 0;
	return;
}

/* ---------------------------------------------------------------------- */

MODULE_AUTHOR("Gerd Knorr, Pavel Machek, Chris Pascoe");
MODULE_DESCRIPTION("input driver for cx88 GPIO-based IR remote controls");
MODULE_LICENSE("GPL");
/*
 * Local variables:
 * c-basic-offset: 8
 * End:
 */