diff options
author | Dmitry Torokhov <dtor@insightbb.com> | 2007-05-01 06:24:54 +0200 |
---|---|---|
committer | Dmitry Torokhov <dtor@insightbb.com> | 2007-05-01 06:24:54 +0200 |
commit | bc95f3669f5e6f63cf0b84fe4922c3c6dd4aa775 (patch) | |
tree | 427fcf2a7287c16d4b5aa6cbf494d59579a6a8b1 /drivers/media/dvb/ttpci/budget-ci.c | |
parent | Input: cobalt_btns - convert to use polldev library (diff) | |
parent | libata: honour host controllers that want just one host (diff) | |
download | linux-bc95f3669f5e6f63cf0b84fe4922c3c6dd4aa775.tar.xz linux-bc95f3669f5e6f63cf0b84fe4922c3c6dd4aa775.zip |
Merge master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts:
drivers/usb/input/Makefile
drivers/usb/input/gtco.c
Diffstat (limited to 'drivers/media/dvb/ttpci/budget-ci.c')
-rw-r--r-- | drivers/media/dvb/ttpci/budget-ci.c | 133 |
1 files changed, 72 insertions, 61 deletions
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index f2066b47baee..4ed4599ce816 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -29,8 +29,6 @@ * the project's page is at http://www.linuxtv.org/dvb/ */ -#include "budget.h" - #include <linux/module.h> #include <linux/errno.h> #include <linux/slab.h> @@ -39,6 +37,8 @@ #include <linux/spinlock.h> #include <media/ir-common.h> +#include "budget.h" + #include "dvb_ca_en50221.h" #include "stv0299.h" #include "stv0297.h" @@ -73,21 +73,15 @@ #define SLOTSTATUS_READY 8 #define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY) -/* Milliseconds during which key presses are regarded as key repeat and during - * which the debounce logic is active +/* + * Milliseconds during which a key is regarded as pressed. + * If an identical command arrives within this time, the timer will start over. */ -#define IR_REPEAT_TIMEOUT 350 +#define IR_KEYPRESS_TIMEOUT 250 /* RC5 device wildcard */ #define IR_DEVICE_ANY 255 -/* Some remotes sends multiple sequences per keypress (e.g. Zenith sends two), - * this setting allows the superflous sequences to be ignored - */ -static int debounce = 0; -module_param(debounce, int, 0644); -MODULE_PARM_DESC(debounce, "ignore repeated IR sequences (default: 0 = ignore no sequences)"); - static int rc5_device = -1; module_param(rc5_device, int, 0644); MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)"); @@ -99,10 +93,14 @@ MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding"); struct budget_ci_ir { struct input_dev *dev; struct tasklet_struct msp430_irq_tasklet; + struct timer_list timer_keyup; char name[72]; /* 40 + 32 for (struct saa7146_dev).name */ char phys[32]; struct ir_input_state state; int rc5_device; + u32 last_raw; + u32 ir_key; + bool have_command; }; struct budget_ci { @@ -125,12 +123,8 @@ static void msp430_ir_interrupt(unsigned long data) { struct budget_ci *budget_ci = (struct budget_ci *) data; struct input_dev *dev = budget_ci->ir.dev; - static int bounces = 0; - int device; - int toggle; - static int prev_toggle = -1; - static u32 ir_key; u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8; + u32 raw; /* * The msp430 chip can generate two different bytes, command and device @@ -138,53 +132,48 @@ static void msp430_ir_interrupt(unsigned long data) * type1: X1CCCCCC, C = command bits (0 - 63) * type2: X0TDDDDD, D = device bits (0 - 31), T = RC5 toggle bit * - * More than one command byte may be generated before the device byte - * Only when we have both, a correct keypress is generated + * Each signal from the remote control can generate one or more command + * bytes and one or more device bytes. For the repeated bytes, the + * highest bit (X) is set. The first command byte is always generated + * before the first device byte. Other than that, no specific order + * seems to apply. To make life interesting, bytes can also be lost. + * + * Only when we have a command and device byte, a keypress is + * generated. */ + if (ir_debug) + printk("budget_ci: received byte 0x%02x\n", command); + + /* Remove repeat bit, we use every command */ + command = command & 0x7f; + /* Is this a RC5 command byte? */ if (command & 0x40) { - if (ir_debug) - printk("budget_ci: received command byte 0x%02x\n", command); - ir_key = command & 0x3f; + budget_ci->ir.have_command = true; + budget_ci->ir.ir_key = command & 0x3f; return; } /* It's a RC5 device byte */ - if (ir_debug) - printk("budget_ci: received device byte 0x%02x\n", command); - device = command & 0x1f; - toggle = command & 0x20; - - if (budget_ci->ir.rc5_device != IR_DEVICE_ANY && budget_ci->ir.rc5_device != device) + if (!budget_ci->ir.have_command) return; + budget_ci->ir.have_command = false; - /* Ignore repeated key sequences if requested */ - if (toggle == prev_toggle && ir_key == dev->repeat_key && - bounces > 0 && timer_pending(&dev->timer)) { - if (ir_debug) - printk("budget_ci: debounce logic ignored IR command\n"); - bounces--; + if (budget_ci->ir.rc5_device != IR_DEVICE_ANY && + budget_ci->ir.rc5_device != (command & 0x1f)) return; - } - prev_toggle = toggle; - - /* Are we still waiting for a keyup event? */ - if (del_timer(&dev->timer)) - ir_input_nokey(dev, &budget_ci->ir.state); - /* Generate keypress */ - if (ir_debug) - printk("budget_ci: generating keypress 0x%02x\n", ir_key); - ir_input_keydown(dev, &budget_ci->ir.state, ir_key, (ir_key & (command << 8))); - - /* Do we want to delay the keyup event? */ - if (debounce) { - bounces = debounce; - mod_timer(&dev->timer, jiffies + msecs_to_jiffies(IR_REPEAT_TIMEOUT)); - } else { + /* Is this a repeated key sequence? (same device, command, toggle) */ + raw = budget_ci->ir.ir_key | (command << 8); + if (budget_ci->ir.last_raw != raw || !timer_pending(&budget_ci->ir.timer_keyup)) { ir_input_nokey(dev, &budget_ci->ir.state); + ir_input_keydown(dev, &budget_ci->ir.state, + budget_ci->ir.ir_key, raw); + budget_ci->ir.last_raw = raw; } + + mod_timer(&budget_ci->ir.timer_keyup, jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT)); } static int msp430_ir_init(struct budget_ci *budget_ci) @@ -223,7 +212,6 @@ static int msp430_ir_init(struct budget_ci *budget_ci) switch (budget_ci->budget.dev->pci->subsystem_device) { case 0x100c: case 0x100f: - case 0x1010: case 0x1011: case 0x1012: case 0x1017: @@ -236,6 +224,16 @@ static int msp430_ir_init(struct budget_ci *budget_ci) else budget_ci->ir.rc5_device = rc5_device; break; + case 0x1010: + /* for the Technotrend 1500 bundled remote */ + ir_input_init(input_dev, &budget_ci->ir.state, + IR_TYPE_RC5, ir_codes_tt_1500); + + if (rc5_device < 0) + budget_ci->ir.rc5_device = IR_DEVICE_ANY; + else + budget_ci->ir.rc5_device = rc5_device; + break; default: /* unknown remote */ ir_input_init(input_dev, &budget_ci->ir.state, @@ -248,16 +246,21 @@ static int msp430_ir_init(struct budget_ci *budget_ci) break; } - /* initialise the key-up debounce timeout handler */ - input_dev->timer.function = msp430_ir_keyup; - input_dev->timer.data = (unsigned long) &budget_ci->ir; - + /* initialise the key-up timeout handler */ + init_timer(&budget_ci->ir.timer_keyup); + budget_ci->ir.timer_keyup.function = msp430_ir_keyup; + budget_ci->ir.timer_keyup.data = (unsigned long) &budget_ci->ir; + budget_ci->ir.last_raw = 0xffff; /* An impossible value */ error = input_register_device(input_dev); if (error) { printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error); goto out2; } + /* note: these must be after input_register_device */ + input_dev->rep[REP_DELAY] = 400; + input_dev->rep[REP_PERIOD] = 250; + tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt, (unsigned long) budget_ci); @@ -281,10 +284,8 @@ static void msp430_ir_deinit(struct budget_ci *budget_ci) saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT); tasklet_kill(&budget_ci->ir.msp430_irq_tasklet); - if (del_timer(&dev->timer)) { - ir_input_nokey(dev, &budget_ci->ir.state); - input_sync(dev); - } + del_timer_sync(&dev->timer); + ir_input_nokey(dev, &budget_ci->ir.state); input_unregister_device(dev); } @@ -869,6 +870,17 @@ static struct tda1004x_config philips_tdm1316l_config = { .request_firmware = philips_tdm1316l_request_firmware, }; +static struct tda1004x_config philips_tdm1316l_config_invert = { + + .demod_address = 0x8, + .invert = 1, + .invert_oclk = 0, + .xtal_freq = TDA10046_XTAL_4M, + .agc_config = TDA10046_AGC_DEFAULT, + .if_freq = TDA10046_FREQ_3617, + .request_firmware = philips_tdm1316l_request_firmware, +}; + static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv; @@ -1092,9 +1104,8 @@ static void frontend_init(struct budget_ci *budget_ci) case 0x1012: // TT DVB-T CI budget (tda10046/Philips tdm1316l(tda6651tt)) budget_ci->tuner_pll_address = 0x60; - philips_tdm1316l_config.invert = 1; budget_ci->budget.dvb_frontend = - dvb_attach(tda10046_attach, &philips_tdm1316l_config, &budget_ci->budget.i2c_adap); + dvb_attach(tda10046_attach, &philips_tdm1316l_config_invert, &budget_ci->budget.i2c_adap); if (budget_ci->budget.dvb_frontend) { budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init; budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params; |