cx88-input.c 15.1 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-core.h>
34
#include <media/ir-common.h>
L
Linus Torvalds 已提交
35

36 37
#define MODULE_NAME "cx88xx"

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

struct cx88_IR {
M
Mauro Carvalho Chehab 已提交
41
	struct cx88_core *core;
42
	struct input_dev *input;
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;
L
Linus Torvalds 已提交
52 53

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

63 64 65 66
static unsigned ir_samplerate = 4;
module_param(ir_samplerate, uint, 0444);
MODULE_PARM_DESC(ir_samplerate, "IR samplerate in kHz, 1 - 20, default 4");

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

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

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

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

	/* read gpio value */
	gpio = cx_read(ir->gpio_addr);
83
	switch (core->boardnr) {
84
	case CX88_BOARD_NPGTECH_REALTV_TOP10FM:
85 86 87 88 89 90 91 92 93 94 95 96 97 98
		/* 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 */
99
		gpio=(gpio & 0x7fd) + (auxgpio & 0xef);
100 101
		break;
	case CX88_BOARD_WINFAST_DTV1000:
102
	case CX88_BOARD_WINFAST_DTV1800H:
103
	case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
104 105
		gpio = (gpio & 0x6ff) | ((cx_read(MO_GP1_IO) << 8) & 0x900);
		auxgpio = gpio;
106 107
		break;
	default:
108
		auxgpio = gpio;
109
	}
L
Linus Torvalds 已提交
110
	if (ir->polling) {
111
		if (ir->last_gpio == auxgpio)
L
Linus Torvalds 已提交
112
			return;
113
		ir->last_gpio = auxgpio;
L
Linus Torvalds 已提交
114 115 116 117 118
	}

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

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

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

129
		ir_keydown(ir->input, data, 0);
130 131

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

	} else if (ir->mask_keyup) {
		/* bit cleared on keydown */
138 139
		if (0 == (gpio & ir->mask_keyup))
			ir_keydown(ir->input, data, 0);
L
Linus Torvalds 已提交
140 141 142

	} else {
		/* can't distinguish keydown/up :-/ */
143
		ir_keydown(ir->input, data, 0);
L
Linus Torvalds 已提交
144 145 146
	}
}

147
static enum hrtimer_restart cx88_ir_work(struct hrtimer *timer)
L
Linus Torvalds 已提交
148
{
149 150
	unsigned long missed;
	struct cx88_IR *ir = container_of(timer, struct cx88_IR, timer);
L
Linus Torvalds 已提交
151 152

	cx88_ir_handle_key(ir);
153 154 155 156 157 158
	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 已提交
159 160
}

161
static int __cx88_ir_start(void *priv)
162
{
163 164 165 166 167 168 169 170
	struct cx88_core *core = priv;
	struct cx88_IR *ir;

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

	ir = core->ir;

171
	if (ir->polling) {
172 173 174 175 176
		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);
177 178
	}
	if (ir->sampling) {
179
		core->pci_irqmask |= PCI_INT_IR_SMPINT;
180 181
		cx_write(MO_DDS_IO, 0x33F286 * ir_samplerate); /* samplerate */
		cx_write(MO_DDSCFG_IO, 0x5); /* enable */
182
	}
183
	return 0;
184 185
}

186
static void __cx88_ir_stop(void *priv)
187
{
188 189 190 191 192 193 194
	struct cx88_core *core = priv;
	struct cx88_IR *ir;

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

	ir = core->ir;
195 196
	if (ir->sampling) {
		cx_write(MO_DDSCFG_IO, 0x0);
197
		core->pci_irqmask &= ~PCI_INT_IR_SMPINT;
198 199
	}

200
	if (ir->polling)
201
		hrtimer_cancel(&ir->timer);
202 203
}

204 205 206 207 208 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
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 已提交
235 236 237 238 239
/* ---------------------------------------------------------------------- */

int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
{
	struct cx88_IR *ir;
240
	struct input_dev *input_dev;
241
	char *ir_codes = NULL;
242
	u64 ir_type = IR_TYPE_OTHER;
243
	int err = -ENOMEM;
244 245 246
	u32 hardware_mask = 0;	/* For devices with a hardware mask, when
				 * used with a full-code IR table
				 */
L
Linus Torvalds 已提交
247

248 249
	ir = kzalloc(sizeof(*ir), GFP_KERNEL);
	input_dev = input_allocate_device();
250 251
	if (!ir || !input_dev)
		goto err_out_free;
252 253

	ir->input = input_dev;
L
Linus Torvalds 已提交
254 255

	/* detect & configure */
256
	switch (core->boardnr) {
L
Linus Torvalds 已提交
257
	case CX88_BOARD_DNTV_LIVE_DVB_T:
258
	case CX88_BOARD_KWORLD_DVB_T:
259
	case CX88_BOARD_KWORLD_DVB_T_CX22702:
260
		ir_codes = RC_MAP_DNTV_LIVE_DVB_T;
M
Mauro Carvalho Chehab 已提交
261
		ir->gpio_addr = MO_GP1_IO;
L
Linus Torvalds 已提交
262
		ir->mask_keycode = 0x1f;
M
Mauro Carvalho Chehab 已提交
263 264
		ir->mask_keyup = 0x60;
		ir->polling = 50; /* ms */
L
Linus Torvalds 已提交
265
		break;
266
	case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
267
		ir_codes = RC_MAP_CINERGY_1400;
268
		ir->sampling = 0xeb04; /* address */
269
		break;
L
Linus Torvalds 已提交
270 271
	case CX88_BOARD_HAUPPAUGE:
	case CX88_BOARD_HAUPPAUGE_DVB_T1:
272 273
	case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
	case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
274
	case CX88_BOARD_HAUPPAUGE_HVR1100:
275
	case CX88_BOARD_HAUPPAUGE_HVR3000:
276 277
	case CX88_BOARD_HAUPPAUGE_HVR4000:
	case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
278 279
	case CX88_BOARD_PCHDTV_HD3000:
	case CX88_BOARD_PCHDTV_HD5500:
280
	case CX88_BOARD_HAUPPAUGE_IRONLY:
281
		ir_codes = RC_MAP_HAUPPAUGE_NEW;
M
Mauro Carvalho Chehab 已提交
282
		ir->sampling = 1;
L
Linus Torvalds 已提交
283
		break;
284
	case CX88_BOARD_WINFAST_DTV2000H:
285
	case CX88_BOARD_WINFAST_DTV2000H_J:
286
	case CX88_BOARD_WINFAST_DTV1800H:
287
		ir_codes = RC_MAP_WINFAST;
M
Mauro Carvalho Chehab 已提交
288
		ir->gpio_addr = MO_GP0_IO;
L
Linus Torvalds 已提交
289
		ir->mask_keycode = 0x8f8;
M
Mauro Carvalho Chehab 已提交
290
		ir->mask_keyup = 0x100;
291
		ir->polling = 50; /* ms */
L
Linus Torvalds 已提交
292
		break;
293
	case CX88_BOARD_WINFAST2000XP_EXPERT:
294
	case CX88_BOARD_WINFAST_DTV1000:
295
	case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
296
		ir_codes = RC_MAP_WINFAST;
297 298 299 300 301
		ir->gpio_addr = MO_GP0_IO;
		ir->mask_keycode = 0x8f8;
		ir->mask_keyup = 0x100;
		ir->polling = 1; /* ms */
		break;
L
Linus Torvalds 已提交
302
	case CX88_BOARD_IODATA_GVBCTV7E:
303
		ir_codes = RC_MAP_IODATA_BCTV7E;
M
Mauro Carvalho Chehab 已提交
304
		ir->gpio_addr = MO_GP0_IO;
L
Linus Torvalds 已提交
305 306
		ir->mask_keycode = 0xfd;
		ir->mask_keydown = 0x02;
M
Mauro Carvalho Chehab 已提交
307
		ir->polling = 5; /* ms */
L
Linus Torvalds 已提交
308
		break;
309
	case CX88_BOARD_PROLINK_PLAYTVPVR:
310
	case CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO:
311 312 313 314 315 316 317 318
		/*
		 * 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 已提交
319 320
		ir->gpio_addr = MO_GP1_IO;
		ir->mask_keyup = 0x80;
321
		ir->polling = 10; /* ms */
322
		hardware_mask = 0x3f;	/* Hardware returns only 6 bits from command part */
323
		break;
324
	case CX88_BOARD_PROLINK_PV_8000GT:
325
	case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
326
		ir_codes = RC_MAP_PIXELVIEW_NEW;
327 328 329 330 331
		ir->gpio_addr = MO_GP1_IO;
		ir->mask_keycode = 0x3f;
		ir->mask_keyup = 0x80;
		ir->polling = 1; /* ms */
		break;
332
	case CX88_BOARD_KWORLD_LTV883:
333
		ir_codes = RC_MAP_PIXELVIEW;
334 335 336 337 338
		ir->gpio_addr = MO_GP1_IO;
		ir->mask_keycode = 0x1f;
		ir->mask_keyup = 0x60;
		ir->polling = 1; /* ms */
		break;
M
Mauro Carvalho Chehab 已提交
339
	case CX88_BOARD_ADSTECH_DVB_T_PCI:
340
		ir_codes = RC_MAP_ADSTECH_DVB_T_PCI;
M
Mauro Carvalho Chehab 已提交
341
		ir->gpio_addr = MO_GP1_IO;
M
Mauro Carvalho Chehab 已提交
342
		ir->mask_keycode = 0xbf;
M
Mauro Carvalho Chehab 已提交
343 344 345 346
		ir->mask_keyup = 0x40;
		ir->polling = 50; /* ms */
		break;
	case CX88_BOARD_MSI_TVANYWHERE_MASTER:
347
		ir_codes = RC_MAP_MSI_TVANYWHERE;
M
Mauro Carvalho Chehab 已提交
348 349 350 351
		ir->gpio_addr = MO_GP1_IO;
		ir->mask_keycode = 0x1f;
		ir->mask_keyup = 0x40;
		ir->polling = 1; /* ms */
M
Mauro Carvalho Chehab 已提交
352
		break;
353
	case CX88_BOARD_AVERTV_303:
354
	case CX88_BOARD_AVERTV_STUDIO_303:
355
		ir_codes         = RC_MAP_AVERTV_303;
356 357 358 359 360
		ir->gpio_addr    = MO_GP2_IO;
		ir->mask_keycode = 0xfb;
		ir->mask_keydown = 0x02;
		ir->polling      = 50; /* ms */
		break;
361 362 363 364 365
	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:
366
	case CX88_BOARD_PROF_7301:
367
	case CX88_BOARD_PROF_6200:
368
		ir_codes = RC_MAP_TBS_NEC;
369 370 371 372
		ir->sampling = 0xff00; /* address */
		break;
	case CX88_BOARD_TEVII_S460:
	case CX88_BOARD_TEVII_S420:
373
		ir_codes = RC_MAP_TEVII_NEC;
374 375
		ir->sampling = 0xff00; /* address */
		break;
376
	case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
377
		ir_codes         = RC_MAP_DNTV_LIVE_DVBT_PRO;
378
		ir->sampling     = 0xff00; /* address */
379
		break;
380
	case CX88_BOARD_NORWOOD_MICRO:
381
		ir_codes         = RC_MAP_NORWOOD;
382 383 384 385 386
		ir->gpio_addr    = MO_GP1_IO;
		ir->mask_keycode = 0x0e;
		ir->mask_keyup   = 0x80;
		ir->polling      = 50; /* ms */
		break;
387
	case CX88_BOARD_NPGTECH_REALTV_TOP10FM:
388
		ir_codes         = RC_MAP_NPGTECH;
389
		ir->gpio_addr    = MO_GP0_IO;
390
		ir->mask_keycode = 0xfa;
391
		ir->polling      = 50; /* ms */
392
		break;
393
	case CX88_BOARD_PINNACLE_PCTV_HD_800i:
394
		ir_codes         = RC_MAP_PINNACLE_PCTV_HD;
395
		ir->sampling     = 1;
396
		break;
397
	case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
398
		ir_codes         = RC_MAP_POWERCOLOR_REAL_ANGEL;
399
		ir->gpio_addr    = MO_GP2_IO;
400
		ir->mask_keycode = 0x7e;
401
		ir->polling      = 100; /* ms */
402
		break;
403 404 405 406 407
	case CX88_BOARD_TWINHAN_VP1027_DVBS:
		ir_codes         = RC_MAP_TWINHAN_VP1027_DVBS;
		ir_type          = IR_TYPE_NEC;
		ir->sampling     = 0xff00; /* address */
		break;
L
Linus Torvalds 已提交
408
	}
409

410
	if (!ir_codes) {
411 412
		err = -ENODEV;
		goto err_out_free;
L
Linus Torvalds 已提交
413 414
	}

415 416 417 418 419 420 421 422 423 424 425 426 427 428 429
	/*
	 * 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 已提交
430
	/* init input device */
431
	snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", core->board.name);
M
Mauro Carvalho Chehab 已提交
432
	snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci));
L
Linus Torvalds 已提交
433

434 435 436 437
	input_dev->name = ir->name;
	input_dev->phys = ir->phys;
	input_dev->id.bustype = BUS_PCI;
	input_dev->id.version = 1;
L
Linus Torvalds 已提交
438
	if (pci->subsystem_vendor) {
439 440
		input_dev->id.vendor = pci->subsystem_vendor;
		input_dev->id.product = pci->subsystem_device;
L
Linus Torvalds 已提交
441
	} else {
442 443
		input_dev->id.vendor = pci->vendor;
		input_dev->id.product = pci->device;
L
Linus Torvalds 已提交
444
	}
445
	input_dev->dev.parent = &pci->dev;
L
Linus Torvalds 已提交
446 447 448 449
	/* record handles to ourself */
	ir->core = core;
	core->ir = ir;

450 451 452 453 454 455 456
	if (ir->sampling) {
		ir_type = IR_TYPE_ALL;
		ir->props.driver_type = RC_DRIVER_IR_RAW;
		ir->props.timeout = 10 * 1000 * 1000; /* 10 ms */
	} else
		ir->props.driver_type = RC_DRIVER_SCANCODE;

457 458 459
	ir->props.priv = core;
	ir->props.open = cx88_ir_open;
	ir->props.close = cx88_ir_close;
460
	ir->props.scanmask = hardware_mask;
461
	ir->props.allowed_protos = ir_type;
L
Linus Torvalds 已提交
462 463

	/* all done */
464
	err = ir_input_register(ir->input, ir_codes, &ir->props, MODULE_NAME);
465
	if (err)
466
		goto err_out_free;
L
Linus Torvalds 已提交
467 468

	return 0;
469 470

 err_out_free:
471
	core->ir = NULL;
472 473
	kfree(ir);
	return err;
L
Linus Torvalds 已提交
474 475 476 477 478 479 480 481 482 483
}

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;

484
	cx88_ir_stop(core);
485
	ir_input_unregister(ir->input);
L
Linus Torvalds 已提交
486 487 488 489 490 491 492 493 494 495 496 497
	kfree(ir);

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

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

void cx88_ir_irq(struct cx88_core *core)
{
	struct cx88_IR *ir = core->ir;
498 499 500 501
	u32 samples;
	unsigned todo, bits;
	struct ir_raw_event ev;
	struct ir_input_dev *irdev;
L
Linus Torvalds 已提交
502

503
	if (!ir || !ir->sampling)
L
Linus Torvalds 已提交
504 505
		return;

506 507 508 509 510
	/*
	 * Samples are stored in a 32 bit register, oldest sample in
	 * the msb. A set bit represents space and an unset bit
	 * represents a pulse.
	 */
L
Linus Torvalds 已提交
511
	samples = cx_read(MO_SAMPLE_IO);
512
       	irdev = input_get_drvdata(ir->input);
513

514 515
	if (samples == 0xff && irdev->idle)
		return;
516

517 518 519 520 521 522 523
	init_ir_raw_event(&ev);
	for (todo = 32; todo > 0; todo -= bits) {
		ev.pulse = samples & 0x80000000 ? false : true;
		bits = min(todo, 32U - fls(ev.pulse ? samples : ~samples));
		ev.duration = (bits * NSEC_PER_SEC) / (1000 * ir_samplerate);
		ir_raw_event_store_with_filter(ir->input, &ev);
		samples <<= bits;
L
Linus Torvalds 已提交
524
	}
525
	ir_raw_event_handle(ir->input);
L
Linus Torvalds 已提交
526 527
}

528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572
void cx88_i2c_init_ir(struct cx88_core *core)
{
	struct i2c_board_info info;
	const unsigned short addr_list[] = {
		0x18, 0x6b, 0x71,
		I2C_CLIENT_END
	};
	const unsigned short *addrp;
	/* Instantiate the IR receiver device, if present */
	if (0 != core->i2c_rc)
		return;

	memset(&info, 0, sizeof(struct i2c_board_info));
	strlcpy(info.type, "ir_video", I2C_NAME_SIZE);

	/*
	 * We can't call i2c_new_probed_device() because it uses
	 * quick writes for probing and at least some RC receiver
	 * devices only reply to reads.
	 * Also, Hauppauge XVR needs to be specified, as address 0x71
	 * conflicts with another remote type used with saa7134
	 */
	for (addrp = addr_list; *addrp != I2C_CLIENT_END; addrp++) {
		info.platform_data = NULL;
		memset(&core->init_data, 0, sizeof(core->init_data));

		if (*addrp == 0x71) {
			/* Hauppauge XVR */
			core->init_data.name = "cx88 Hauppauge XVR remote";
			core->init_data.ir_codes = RC_MAP_HAUPPAUGE_NEW;
			core->init_data.type = IR_TYPE_RC5;
			core->init_data.internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;

			info.platform_data = &core->init_data;
		}
		if (i2c_smbus_xfer(&core->i2c_adap, *addrp, 0,
					I2C_SMBUS_READ, 0,
					I2C_SMBUS_QUICK, NULL) >= 0) {
			info.addr = *addrp;
			i2c_new_device(&core->i2c_adap, &info);
			break;
		}
	}
}

L
Linus Torvalds 已提交
573 574 575 576 577
/* ---------------------------------------------------------------------- */

MODULE_AUTHOR("Gerd Knorr, Pavel Machek, Chris Pascoe");
MODULE_DESCRIPTION("input driver for cx88 GPIO-based IR remote controls");
MODULE_LICENSE("GPL");