cx88-input.c 16.6 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7
/*
 *
 * 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
8
 * Copyright (c) 2004, 2005 Chris Pascoe
L
Linus Torvalds 已提交
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 *
 * 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>
26
#include <linux/hrtimer.h>
L
Linus Torvalds 已提交
27 28
#include <linux/input.h>
#include <linux/pci.h>
29
#include <linux/slab.h>
L
Linus Torvalds 已提交
30 31 32
#include <linux/module.h>

#include "cx88.h"
33
#include <media/ir-common.h>
L
Linus Torvalds 已提交
34

35 36
#define MODULE_NAME "cx88xx"

L
Linus Torvalds 已提交
37 38 39
/* ---------------------------------------------------------------------- */

struct cx88_IR {
M
Mauro Carvalho Chehab 已提交
40
	struct cx88_core *core;
41
	struct input_dev *input;
M
Mauro Carvalho Chehab 已提交
42
	struct ir_input_state ir;
43 44 45 46
	struct ir_dev_props props;

	int users;

M
Mauro Carvalho Chehab 已提交
47 48
	char name[32];
	char phys[32];
L
Linus Torvalds 已提交
49 50

	/* sample from gpio pin 16 */
51
	u32 sampling;
M
Mauro Carvalho Chehab 已提交
52 53 54
	u32 samples[16];
	int scount;
	unsigned long release;
L
Linus Torvalds 已提交
55 56

	/* poll external decoder */
M
Mauro Carvalho Chehab 已提交
57
	int polling;
58
	struct hrtimer timer;
M
Mauro Carvalho Chehab 已提交
59 60 61 62 63
	u32 gpio_addr;
	u32 last_gpio;
	u32 mask_keycode;
	u32 mask_keydown;
	u32 mask_keyup;
L
Linus Torvalds 已提交
64 65
};

66
static int ir_debug;
M
Mauro Carvalho Chehab 已提交
67
module_param(ir_debug, int, 0644);	/* debug level [IR] */
L
Linus Torvalds 已提交
68 69 70
MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");

#define ir_dprintk(fmt, arg...)	if (ir_debug) \
71
	printk(KERN_DEBUG "%s IR: " fmt , ir->core->name , ##arg)
L
Linus Torvalds 已提交
72 73 74 75 76 77

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

static void cx88_ir_handle_key(struct cx88_IR *ir)
{
	struct cx88_core *core = ir->core;
78
	u32 gpio, data, auxgpio;
L
Linus Torvalds 已提交
79 80 81

	/* read gpio value */
	gpio = cx_read(ir->gpio_addr);
82
	switch (core->boardnr) {
83
	case CX88_BOARD_NPGTECH_REALTV_TOP10FM:
84 85 86 87 88 89 90 91 92 93 94 95 96 97
		/* This board apparently uses a combination of 2 GPIO
		   to represent the keys. Additionally, the second GPIO
		   can be used for parity.

		   Example:

		   for key "5"
			gpio = 0x758, auxgpio = 0xe5 or 0xf5
		   for key "Power"
			gpio = 0x758, auxgpio = 0xed or 0xfd
		 */

		auxgpio = cx_read(MO_GP1_IO);
		/* Take out the parity part */
98
		gpio=(gpio & 0x7fd) + (auxgpio & 0xef);
99 100
		break;
	case CX88_BOARD_WINFAST_DTV1000:
101
	case CX88_BOARD_WINFAST_DTV1800H:
102
	case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
103 104
		gpio = (gpio & 0x6ff) | ((cx_read(MO_GP1_IO) << 8) & 0x900);
		auxgpio = gpio;
105 106
		break;
	default:
107
		auxgpio = gpio;
108
	}
L
Linus Torvalds 已提交
109
	if (ir->polling) {
110
		if (ir->last_gpio == auxgpio)
L
Linus Torvalds 已提交
111
			return;
112
		ir->last_gpio = auxgpio;
L
Linus Torvalds 已提交
113 114 115 116 117
	}

	/* 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 已提交
118 119 120 121
		   gpio, data,
		   ir->polling ? "poll" : "irq",
		   (gpio & ir->mask_keydown) ? " down" : "",
		   (gpio & ir->mask_keyup) ? " up" : "");
L
Linus Torvalds 已提交
122

123
	if (ir->core->boardnr == CX88_BOARD_NORWOOD_MICRO) {
124 125 126 127
		u32 gpio_key = cx_read(MO_GP0_IO);

		data = (data << 4) | ((gpio_key & 0xf0) >> 4);

128
		ir_input_keydown(ir->input, &ir->ir, data);
129 130 131
		ir_input_nokey(ir->input, &ir->ir);

	} else if (ir->mask_keydown) {
L
Linus Torvalds 已提交
132 133
		/* bit set on keydown */
		if (gpio & ir->mask_keydown) {
134
			ir_input_keydown(ir->input, &ir->ir, data);
L
Linus Torvalds 已提交
135
		} else {
136
			ir_input_nokey(ir->input, &ir->ir);
L
Linus Torvalds 已提交
137 138 139 140 141
		}

	} else if (ir->mask_keyup) {
		/* bit cleared on keydown */
		if (0 == (gpio & ir->mask_keyup)) {
142
			ir_input_keydown(ir->input, &ir->ir, data);
L
Linus Torvalds 已提交
143
		} else {
144
			ir_input_nokey(ir->input, &ir->ir);
L
Linus Torvalds 已提交
145 146 147 148
		}

	} else {
		/* can't distinguish keydown/up :-/ */
149
		ir_input_keydown(ir->input, &ir->ir, data);
150
		ir_input_nokey(ir->input, &ir->ir);
L
Linus Torvalds 已提交
151 152 153
	}
}

154
static enum hrtimer_restart cx88_ir_work(struct hrtimer *timer)
L
Linus Torvalds 已提交
155
{
156 157
	unsigned long missed;
	struct cx88_IR *ir = container_of(timer, struct cx88_IR, timer);
L
Linus Torvalds 已提交
158 159

	cx88_ir_handle_key(ir);
160 161 162 163 164 165
	missed = hrtimer_forward_now(&ir->timer,
				     ktime_set(0, ir->polling * 1000000));
	if (missed > 1)
		ir_dprintk("Missed ticks %ld\n", missed - 1);

	return HRTIMER_RESTART;
L
Linus Torvalds 已提交
166 167
}

168
static int __cx88_ir_start(void *priv)
169
{
170 171 172 173 174 175 176 177
	struct cx88_core *core = priv;
	struct cx88_IR *ir;

	if (!core || !core->ir)
		return -EINVAL;

	ir = core->ir;

178
	if (ir->polling) {
179 180 181 182 183
		hrtimer_init(&ir->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
		ir->timer.function = cx88_ir_work;
		hrtimer_start(&ir->timer,
			      ktime_set(0, ir->polling * 1000000),
			      HRTIMER_MODE_REL);
184 185
	}
	if (ir->sampling) {
186
		core->pci_irqmask |= PCI_INT_IR_SMPINT;
187 188 189
		cx_write(MO_DDS_IO, 0xa80a80);	/* 4 kHz sample rate */
		cx_write(MO_DDSCFG_IO, 0x5);	/* enable */
	}
190
	return 0;
191 192
}

193
static void __cx88_ir_stop(void *priv)
194
{
195 196 197 198 199 200 201
	struct cx88_core *core = priv;
	struct cx88_IR *ir;

	if (!core || !core->ir)
		return;

	ir = core->ir;
202 203
	if (ir->sampling) {
		cx_write(MO_DDSCFG_IO, 0x0);
204
		core->pci_irqmask &= ~PCI_INT_IR_SMPINT;
205 206
	}

207
	if (ir->polling)
208
		hrtimer_cancel(&ir->timer);
209 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
int cx88_ir_start(struct cx88_core *core)
{
	if (core->ir->users)
		return __cx88_ir_start(core);

	return 0;
}

void cx88_ir_stop(struct cx88_core *core)
{
	if (core->ir->users)
		__cx88_ir_stop(core);
}

static int cx88_ir_open(void *priv)
{
	struct cx88_core *core = priv;

	core->ir->users++;
	return __cx88_ir_start(core);
}

static void cx88_ir_close(void *priv)
{
	struct cx88_core *core = priv;

	core->ir->users--;
	if (!core->ir->users)
		__cx88_ir_stop(core);
}

L
Linus Torvalds 已提交
242 243 244 245 246
/* ---------------------------------------------------------------------- */

int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
{
	struct cx88_IR *ir;
247
	struct input_dev *input_dev;
248
	char *ir_codes = NULL;
249
	u64 ir_type = IR_TYPE_OTHER;
250
	int err = -ENOMEM;
251 252 253
	u32 hardware_mask = 0;	/* For devices with a hardware mask, when
				 * used with a full-code IR table
				 */
L
Linus Torvalds 已提交
254

255 256
	ir = kzalloc(sizeof(*ir), GFP_KERNEL);
	input_dev = input_allocate_device();
257 258
	if (!ir || !input_dev)
		goto err_out_free;
259 260

	ir->input = input_dev;
L
Linus Torvalds 已提交
261 262

	/* detect & configure */
263
	switch (core->boardnr) {
L
Linus Torvalds 已提交
264
	case CX88_BOARD_DNTV_LIVE_DVB_T:
265
	case CX88_BOARD_KWORLD_DVB_T:
266
	case CX88_BOARD_KWORLD_DVB_T_CX22702:
267
		ir_codes = RC_MAP_DNTV_LIVE_DVB_T;
M
Mauro Carvalho Chehab 已提交
268
		ir->gpio_addr = MO_GP1_IO;
L
Linus Torvalds 已提交
269
		ir->mask_keycode = 0x1f;
M
Mauro Carvalho Chehab 已提交
270 271
		ir->mask_keyup = 0x60;
		ir->polling = 50; /* ms */
L
Linus Torvalds 已提交
272
		break;
273
	case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
274
		ir_codes = RC_MAP_CINERGY_1400;
275
		ir_type = IR_TYPE_PD;
276
		ir->sampling = 0xeb04; /* address */
277
		break;
L
Linus Torvalds 已提交
278 279
	case CX88_BOARD_HAUPPAUGE:
	case CX88_BOARD_HAUPPAUGE_DVB_T1:
280 281
	case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
	case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
282
	case CX88_BOARD_HAUPPAUGE_HVR1100:
283
	case CX88_BOARD_HAUPPAUGE_HVR3000:
284 285
	case CX88_BOARD_HAUPPAUGE_HVR4000:
	case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
286 287
	case CX88_BOARD_PCHDTV_HD3000:
	case CX88_BOARD_PCHDTV_HD5500:
288
	case CX88_BOARD_HAUPPAUGE_IRONLY:
289
		ir_codes = RC_MAP_HAUPPAUGE_NEW;
M
Mauro Carvalho Chehab 已提交
290 291
		ir_type = IR_TYPE_RC5;
		ir->sampling = 1;
L
Linus Torvalds 已提交
292
		break;
293
	case CX88_BOARD_WINFAST_DTV2000H:
294
	case CX88_BOARD_WINFAST_DTV2000H_J:
295
	case CX88_BOARD_WINFAST_DTV1800H:
296
		ir_codes = RC_MAP_WINFAST;
M
Mauro Carvalho Chehab 已提交
297
		ir->gpio_addr = MO_GP0_IO;
L
Linus Torvalds 已提交
298
		ir->mask_keycode = 0x8f8;
M
Mauro Carvalho Chehab 已提交
299
		ir->mask_keyup = 0x100;
300
		ir->polling = 50; /* ms */
L
Linus Torvalds 已提交
301
		break;
302
	case CX88_BOARD_WINFAST2000XP_EXPERT:
303
	case CX88_BOARD_WINFAST_DTV1000:
304
	case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
305
		ir_codes = RC_MAP_WINFAST;
306 307 308 309 310
		ir->gpio_addr = MO_GP0_IO;
		ir->mask_keycode = 0x8f8;
		ir->mask_keyup = 0x100;
		ir->polling = 1; /* ms */
		break;
L
Linus Torvalds 已提交
311
	case CX88_BOARD_IODATA_GVBCTV7E:
312
		ir_codes = RC_MAP_IODATA_BCTV7E;
M
Mauro Carvalho Chehab 已提交
313
		ir->gpio_addr = MO_GP0_IO;
L
Linus Torvalds 已提交
314 315
		ir->mask_keycode = 0xfd;
		ir->mask_keydown = 0x02;
M
Mauro Carvalho Chehab 已提交
316
		ir->polling = 5; /* ms */
L
Linus Torvalds 已提交
317
		break;
318
	case CX88_BOARD_PROLINK_PLAYTVPVR:
319
	case CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO:
320 321 322 323 324 325 326 327
		/*
		 * It seems that this hardware is paired with NEC extended
		 * address 0x866b. So, unfortunately, its usage with other
		 * IR's with different address won't work. Still, there are
		 * other IR's from the same manufacturer that works, like the
		 * 002-T mini RC, provided with newer PV hardware
		 */
		ir_codes = RC_MAP_PIXELVIEW_MK12;
M
Mauro Carvalho Chehab 已提交
328 329
		ir->gpio_addr = MO_GP1_IO;
		ir->mask_keyup = 0x80;
330
		ir->polling = 10; /* ms */
331
		hardware_mask = 0x3f;	/* Hardware returns only 6 bits from command part */
332
		break;
333
	case CX88_BOARD_PROLINK_PV_8000GT:
334
	case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
335
		ir_codes = RC_MAP_PIXELVIEW_NEW;
336 337 338 339 340
		ir->gpio_addr = MO_GP1_IO;
		ir->mask_keycode = 0x3f;
		ir->mask_keyup = 0x80;
		ir->polling = 1; /* ms */
		break;
341
	case CX88_BOARD_KWORLD_LTV883:
342
		ir_codes = RC_MAP_PIXELVIEW;
343 344 345 346 347
		ir->gpio_addr = MO_GP1_IO;
		ir->mask_keycode = 0x1f;
		ir->mask_keyup = 0x60;
		ir->polling = 1; /* ms */
		break;
M
Mauro Carvalho Chehab 已提交
348
	case CX88_BOARD_ADSTECH_DVB_T_PCI:
349
		ir_codes = RC_MAP_ADSTECH_DVB_T_PCI;
M
Mauro Carvalho Chehab 已提交
350
		ir->gpio_addr = MO_GP1_IO;
M
Mauro Carvalho Chehab 已提交
351
		ir->mask_keycode = 0xbf;
M
Mauro Carvalho Chehab 已提交
352 353 354 355
		ir->mask_keyup = 0x40;
		ir->polling = 50; /* ms */
		break;
	case CX88_BOARD_MSI_TVANYWHERE_MASTER:
356
		ir_codes = RC_MAP_MSI_TVANYWHERE;
M
Mauro Carvalho Chehab 已提交
357 358 359 360
		ir->gpio_addr = MO_GP1_IO;
		ir->mask_keycode = 0x1f;
		ir->mask_keyup = 0x40;
		ir->polling = 1; /* ms */
M
Mauro Carvalho Chehab 已提交
361
		break;
362
	case CX88_BOARD_AVERTV_303:
363
	case CX88_BOARD_AVERTV_STUDIO_303:
364
		ir_codes         = RC_MAP_AVERTV_303;
365 366 367 368 369
		ir->gpio_addr    = MO_GP2_IO;
		ir->mask_keycode = 0xfb;
		ir->mask_keydown = 0x02;
		ir->polling      = 50; /* ms */
		break;
370 371 372 373 374
	case CX88_BOARD_OMICOM_SS4_PCI:
	case CX88_BOARD_SATTRADE_ST4200:
	case CX88_BOARD_TBS_8920:
	case CX88_BOARD_TBS_8910:
	case CX88_BOARD_PROF_7300:
375
	case CX88_BOARD_PROF_7301:
376
	case CX88_BOARD_PROF_6200:
377
		ir_codes = RC_MAP_TBS_NEC;
378 379 380 381 382
		ir_type = IR_TYPE_PD;
		ir->sampling = 0xff00; /* address */
		break;
	case CX88_BOARD_TEVII_S460:
	case CX88_BOARD_TEVII_S420:
383
		ir_codes = RC_MAP_TEVII_NEC;
384 385 386
		ir_type = IR_TYPE_PD;
		ir->sampling = 0xff00; /* address */
		break;
387
	case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
388
		ir_codes         = RC_MAP_DNTV_LIVE_DVBT_PRO;
389 390
		ir_type          = IR_TYPE_PD;
		ir->sampling     = 0xff00; /* address */
391
		break;
392
	case CX88_BOARD_NORWOOD_MICRO:
393
		ir_codes         = RC_MAP_NORWOOD;
394 395 396 397 398
		ir->gpio_addr    = MO_GP1_IO;
		ir->mask_keycode = 0x0e;
		ir->mask_keyup   = 0x80;
		ir->polling      = 50; /* ms */
		break;
399
	case CX88_BOARD_NPGTECH_REALTV_TOP10FM:
400
		ir_codes         = RC_MAP_NPGTECH;
401
		ir->gpio_addr    = MO_GP0_IO;
402
		ir->mask_keycode = 0xfa;
403
		ir->polling      = 50; /* ms */
404
		break;
405
	case CX88_BOARD_PINNACLE_PCTV_HD_800i:
406
		ir_codes         = RC_MAP_PINNACLE_PCTV_HD;
407 408
		ir_type          = IR_TYPE_RC5;
		ir->sampling     = 1;
409
		break;
410
	case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
411
		ir_codes         = RC_MAP_POWERCOLOR_REAL_ANGEL;
412
		ir->gpio_addr    = MO_GP2_IO;
413
		ir->mask_keycode = 0x7e;
414
		ir->polling      = 100; /* ms */
415
		break;
L
Linus Torvalds 已提交
416
	}
417

L
Linus Torvalds 已提交
418
	if (NULL == ir_codes) {
419 420
		err = -ENODEV;
		goto err_out_free;
L
Linus Torvalds 已提交
421 422
	}

423 424 425 426 427 428 429 430 431 432 433 434 435 436 437
	/*
	 * The usage of mask_keycode were very convenient, due to several
	 * reasons. Among others, the scancode tables were using the scancode
	 * as the index elements. So, the less bits it was used, the smaller
	 * the table were stored. After the input changes, the better is to use
	 * the full scancodes, since it allows replacing the IR remote by
	 * another one. Unfortunately, there are still some hardware, like
	 * Pixelview Ultra Pro, where only part of the scancode is sent via
	 * GPIO. So, there's no way to get the full scancode. Due to that,
	 * hardware_mask were introduced here: it represents those hardware
	 * that has such limits.
	 */
	if (hardware_mask && !ir->mask_keycode)
		ir->mask_keycode = hardware_mask;

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

442
	err = ir_input_init(input_dev, &ir->ir, ir_type);
443 444 445
	if (err < 0)
		goto err_out_free;

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

462 463 464
	ir->props.priv = core;
	ir->props.open = cx88_ir_open;
	ir->props.close = cx88_ir_close;
465
	ir->props.scanmask = hardware_mask;
L
Linus Torvalds 已提交
466 467

	/* all done */
468
	err = ir_input_register(ir->input, ir_codes, &ir->props, MODULE_NAME);
469
	if (err)
470
		goto err_out_free;
L
Linus Torvalds 已提交
471 472

	return 0;
473 474

 err_out_free:
475
	core->ir = NULL;
476 477
	kfree(ir);
	return err;
L
Linus Torvalds 已提交
478 479 480 481 482 483 484 485 486 487
}

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;

488
	cx88_ir_stop(core);
489
	ir_input_unregister(ir->input);
L
Linus Torvalds 已提交
490 491 492 493 494 495 496 497 498 499 500 501
	kfree(ir);

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

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

void cx88_ir_irq(struct cx88_core *core)
{
	struct cx88_IR *ir = core->ir;
502
	u32 samples, ircode;
503
	int i, start, range, toggle, dev, code;
L
Linus Torvalds 已提交
504 505 506 507 508 509 510

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

	samples = cx_read(MO_SAMPLE_IO);
M
Mauro Carvalho Chehab 已提交
511
	if (0 != samples && 0xffffffff != samples) {
L
Linus Torvalds 已提交
512 513 514 515 516 517 518
		/* 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 已提交
519
		if (ir->ir.keypressed && time_after(jiffies, ir->release))
520
			ir_input_nokey(ir->input, &ir->ir);
L
Linus Torvalds 已提交
521 522 523 524 525 526 527 528 529
		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 已提交
530
		ir_dump_samples(ir->samples, ir->scount);
L
Linus Torvalds 已提交
531 532

	/* decode it */
533
	switch (core->boardnr) {
534 535
	case CX88_BOARD_TEVII_S460:
	case CX88_BOARD_TEVII_S420:
536
	case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
537
	case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
538 539 540 541 542
	case CX88_BOARD_OMICOM_SS4_PCI:
	case CX88_BOARD_SATTRADE_ST4200:
	case CX88_BOARD_TBS_8920:
	case CX88_BOARD_TBS_8910:
	case CX88_BOARD_PROF_7300:
543
	case CX88_BOARD_PROF_7301:
544
	case CX88_BOARD_PROF_6200:
545 546 547 548 549 550 551 552 553 554 555 556 557 558 559
		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;
		}

560
		if ((ircode & 0xffff) != (ir->sampling & 0xffff)) { /* wrong address */
561
			ir_dprintk("pulse distance decoded wrong address\n");
562
			break;
563 564 565 566 567 568 569 570 571
		}

		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);

572
		ir_input_keydown(ir->input, &ir->ir, (ircode >> 16) & 0x7f);
573 574
		ir->release = jiffies + msecs_to_jiffies(120);
		break;
L
Linus Torvalds 已提交
575 576
	case CX88_BOARD_HAUPPAUGE:
	case CX88_BOARD_HAUPPAUGE_DVB_T1:
577 578
	case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
	case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
C
 
Chris Pascoe 已提交
579
	case CX88_BOARD_HAUPPAUGE_HVR1100:
580
	case CX88_BOARD_HAUPPAUGE_HVR3000:
581 582
	case CX88_BOARD_HAUPPAUGE_HVR4000:
	case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
583 584
	case CX88_BOARD_PCHDTV_HD3000:
	case CX88_BOARD_PCHDTV_HD5500:
585
	case CX88_BOARD_HAUPPAUGE_IRONLY:
586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608
		ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7);
		ir_dprintk("biphase decoded: %x\n", ircode);
		/*
		 * RC5 has an extension bit which adds a new range
		 * of available codes, this is detected here. Also
		 * hauppauge remotes (black/silver) always use
		 * specific device ids. If we do not filter the
		 * device ids then messages destined for devices
		 * such as TVs (id=0) will get through to the
		 * device causing mis-fired events.
		 */
		/* split rc5 data block ... */
		start = (ircode & 0x2000) >> 13;
		range = (ircode & 0x1000) >> 12;
		toggle= (ircode & 0x0800) >> 11;
		dev   = (ircode & 0x07c0) >> 6;
		code  = (ircode & 0x003f) | ((range << 6) ^ 0x0040);
		if( start != 1)
			/* no key pressed */
			break;
		if ( dev != 0x1e && dev != 0x1f )
			/* not a hauppauge remote */
			break;
609
		ir_input_keydown(ir->input, &ir->ir, code);
610 611 612
		ir->release = jiffies + msecs_to_jiffies(120);
		break;
	case CX88_BOARD_PINNACLE_PCTV_HD_800i:
613 614 615
		ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7);
		ir_dprintk("biphase decoded: %x\n", ircode);
		if ((ircode & 0xfffff000) != 0x3000)
L
Linus Torvalds 已提交
616
			break;
617
		ir_input_keydown(ir->input, &ir->ir, ircode & 0x3f);
L
Linus Torvalds 已提交
618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635
		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:
 */