cx88-input.c 14.9 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
#include <linux/pci.h>
28
#include <linux/slab.h>
L
Linus Torvalds 已提交
29 30 31
#include <linux/module.h>

#include "cx88.h"
32
#include <media/rc-core.h>
L
Linus Torvalds 已提交
33

34 35
#define MODULE_NAME "cx88xx"

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

struct cx88_IR {
M
Mauro Carvalho Chehab 已提交
39
	struct cx88_core *core;
40
	struct rc_dev *dev;
41 42 43

	int users;

M
Mauro Carvalho Chehab 已提交
44 45
	char name[32];
	char phys[32];
L
Linus Torvalds 已提交
46 47

	/* sample from gpio pin 16 */
48
	u32 sampling;
L
Linus Torvalds 已提交
49 50

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

60 61 62 63
static unsigned ir_samplerate = 4;
module_param(ir_samplerate, uint, 0444);
MODULE_PARM_DESC(ir_samplerate, "IR samplerate in kHz, 1 - 20, default 4");

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

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

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

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

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

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

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

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

126
		ir_keydown(ir->dev, data, 0);
127 128

	} else if (ir->mask_keydown) {
L
Linus Torvalds 已提交
129
		/* bit set on keydown */
130
		if (gpio & ir->mask_keydown)
131
			ir_keydown_notimeout(ir->dev, data, 0);
132
		else
133
			ir_keyup(ir->dev);
L
Linus Torvalds 已提交
134 135 136

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

	} else {
		/* can't distinguish keydown/up :-/ */
144 145
		ir_keydown_notimeout(ir->dev, data, 0);
		ir_keyup(ir->dev);
L
Linus Torvalds 已提交
146 147 148
	}
}

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

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

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

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

	ir = core->ir;

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

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

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

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

202
	if (ir->polling)
203
		hrtimer_cancel(&ir->timer);
204 205
}

206 207 208 209 210 211 212 213 214 215 216 217 218 219
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);
}

220
static int cx88_ir_open(struct rc_dev *rc)
221
{
222
	struct cx88_core *core = rc->priv;
223 224 225 226 227

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

228
static void cx88_ir_close(struct rc_dev *rc)
229
{
230
	struct cx88_core *core = rc->priv;
231 232 233 234 235 236

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

L
Linus Torvalds 已提交
237 238 239 240 241
/* ---------------------------------------------------------------------- */

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

250
	ir = kzalloc(sizeof(*ir), GFP_KERNEL);
251 252
	dev = rc_allocate_device();
	if (!ir || !dev)
253
		goto err_out_free;
254

255
	ir->dev = dev;
L
Linus Torvalds 已提交
256 257

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

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

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

436 437 438 439
	dev->input_name = ir->name;
	dev->input_phys = ir->phys;
	dev->input_id.bustype = BUS_PCI;
	dev->input_id.version = 1;
L
Linus Torvalds 已提交
440
	if (pci->subsystem_vendor) {
441 442
		dev->input_id.vendor = pci->subsystem_vendor;
		dev->input_id.product = pci->subsystem_device;
L
Linus Torvalds 已提交
443
	} else {
444 445
		dev->input_id.vendor = pci->vendor;
		dev->input_id.product = pci->device;
L
Linus Torvalds 已提交
446
	}
447 448 449 450 451 452 453
	dev->dev.parent = &pci->dev;
	dev->map_name = ir_codes;
	dev->driver_name = MODULE_NAME;
	dev->priv = core;
	dev->open = cx88_ir_open;
	dev->close = cx88_ir_close;
	dev->scanmask = hardware_mask;
L
Linus Torvalds 已提交
454

455
	if (ir->sampling) {
456 457 458 459 460 461 462 463 464
		dev->driver_type = RC_DRIVER_IR_RAW;
		dev->timeout = 10 * 1000 * 1000; /* 10 ms */
	} else {
		dev->driver_type = RC_DRIVER_SCANCODE;
		dev->allowed_protos = ir_type;
	}

	ir->core = core;
	core->ir = ir;
L
Linus Torvalds 已提交
465 466

	/* all done */
467
	err = rc_register_device(dev);
468
	if (err)
469
		goto err_out_free;
L
Linus Torvalds 已提交
470 471

	return 0;
472

473 474
err_out_free:
	rc_free_device(dev);
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
	rc_unregister_device(ir->dev);
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 503 504
	u32 samples;
	unsigned todo, bits;
	struct ir_raw_event ev;
L
Linus Torvalds 已提交
505

506
	if (!ir || !ir->sampling)
L
Linus Torvalds 已提交
507 508
		return;

509 510 511 512 513
	/*
	 * 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 已提交
514
	samples = cx_read(MO_SAMPLE_IO);
515

516
	if (samples == 0xff && ir->dev->idle)
517
		return;
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);
524
		ir_raw_event_store_with_filter(ir->dev, &ev);
525
		samples <<= bits;
L
Linus Torvalds 已提交
526
	}
527
	ir_raw_event_handle(ir->dev);
L
Linus Torvalds 已提交
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 573 574
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 已提交
575 576 577 578 579
/* ---------------------------------------------------------------------- */

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