aboutsummaryrefslogtreecommitdiff
path: root/drivers/media/dvb/ttpci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb/ttpci')
-rw-r--r--drivers/media/dvb/ttpci/Kconfig1
-rw-r--r--drivers/media/dvb/ttpci/budget-ci.c138
2 files changed, 78 insertions, 61 deletions
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig
index 95531a62499..eec7ccf41f8 100644
--- a/drivers/media/dvb/ttpci/Kconfig
+++ b/drivers/media/dvb/ttpci/Kconfig
@@ -92,6 +92,7 @@ config DVB_BUDGET_CI
select DVB_STV0299 if !DVB_FE_CUSTOMISE
select DVB_TDA1004X if !DVB_FE_CUSTOMISE
select DVB_LNBP21 if !DVB_FE_CUSTOMISE
+ select VIDEO_IR
help
Support for simple SAA7146 based DVB cards
(so called Budget- or Nova-PCI cards) without onboard
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index c34b5d3bdde..d1b5402cd6f 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -37,6 +37,7 @@
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/spinlock.h>
+#include <media/ir-common.h>
#include "dvb_ca_en50221.h"
#include "stv0299.h"
@@ -72,11 +73,24 @@
#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
+ */
+#define IR_REPEAT_TIMEOUT 350
+
+/* 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)");
+
struct budget_ci_ir {
struct input_dev *dev;
struct tasklet_struct msp430_irq_tasklet;
char name[72]; /* 40 + 32 for (struct saa7146_dev).name */
char phys[32];
+ struct ir_input_state state;
};
struct budget_ci {
@@ -89,59 +103,44 @@ struct budget_ci {
u8 tuner_pll_address; /* used for philips_tdm1316l configs */
};
-/* from reading the following remotes:
- Zenith Universal 7 / TV Mode 807 / VCR Mode 837
- Hauppauge (from NOVA-CI-s box product)
- i've taken a "middle of the road" approach and note the differences
-*/
-static u16 key_map[64] = {
- /* 0x0X */
- KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8,
- KEY_9,
- KEY_ENTER,
- KEY_RED,
- KEY_POWER, /* RADIO on Hauppauge */
- KEY_MUTE,
- 0,
- KEY_A, /* TV on Hauppauge */
- /* 0x1X */
- KEY_VOLUMEUP, KEY_VOLUMEDOWN,
- 0, 0,
- KEY_B,
- 0, 0, 0, 0, 0, 0, 0,
- KEY_UP, KEY_DOWN,
- KEY_OPTION, /* RESERVED on Hauppauge */
- KEY_BREAK,
- /* 0x2X */
- KEY_CHANNELUP, KEY_CHANNELDOWN,
- KEY_PREVIOUS, /* Prev. Ch on Zenith, SOURCE on Hauppauge */
- 0, KEY_RESTART, KEY_OK,
- KEY_CYCLEWINDOWS, /* MINIMIZE on Hauppauge */
- 0,
- KEY_ENTER, /* VCR mode on Zenith */
- KEY_PAUSE,
- 0,
- KEY_RIGHT, KEY_LEFT,
- 0,
- KEY_MENU, /* FULL SCREEN on Hauppauge */
- 0,
- /* 0x3X */
- KEY_SLOW,
- KEY_PREVIOUS, /* VCR mode on Zenith */
- KEY_REWIND,
- 0,
- KEY_FASTFORWARD,
- KEY_PLAY, KEY_STOP,
- KEY_RECORD,
- KEY_TUNER, /* TV/VCR on Zenith */
- 0,
- KEY_C,
- 0,
- KEY_EXIT,
- KEY_POWER2,
- KEY_TUNER, /* VCR mode on Zenith */
- 0,
-};
+static void msp430_ir_keyup(unsigned long data)
+{
+ struct budget_ci_ir *ir = (struct budget_ci_ir *) data;
+ ir_input_nokey(ir->dev, &ir->state);
+}
+
+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;
+ u32 ir_key;
+ u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
+
+ if (command & 0x40) {
+ ir_key = command & 0x3f;
+
+ if (ir_key != dev->repeat_key && del_timer(&dev->timer))
+ /* We were still waiting for a keyup event but this is a new key */
+ ir_input_nokey(dev, &budget_ci->ir.state);
+
+ if (ir_key == dev->repeat_key && bounces > 0 && timer_pending(&dev->timer)) {
+ /* Ignore repeated key sequences if requested */
+ bounces--;
+ return;
+ }
+
+ if (!timer_pending(&dev->timer))
+ /* New keypress */
+ bounces = debounce;
+
+ /* Prepare a keyup event sometime in the future */
+ mod_timer(&dev->timer, jiffies + msecs_to_jiffies(IR_REPEAT_TIMEOUT));
+
+ /* Generate a new or repeated keypress */
+ ir_input_keydown(dev, &budget_ci->ir.state, ir_key, command);
+ }
+}
static void msp430_ir_debounce(unsigned long data)
{
@@ -197,7 +196,6 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
{
struct saa7146_dev *saa = budget_ci->budget.dev;
struct input_dev *input_dev = budget_ci->ir.dev;
- int i;
int error;
budget_ci->ir.dev = input_dev = input_allocate_device();
@@ -230,10 +228,30 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
input_dev->dev = &saa->pci->dev;
# endif
- set_bit(EV_KEY, input_dev->evbit);
- for (i = 0; i < ARRAY_SIZE(key_map); i++)
- if (key_map[i])
- set_bit(key_map[i], input_dev->keybit);
+ /* Select keymap */
+ switch (budget_ci->budget.dev->pci->subsystem_device) {
+ case 0x100c:
+ case 0x100f:
+ case 0x1010:
+ case 0x1011:
+ case 0x1012:
+ case 0x1017:
+ /* The hauppauge keymap is a superset of these remotes */
+ ir_input_init(input_dev, &budget_ci->ir.state,
+ IR_TYPE_RC5, ir_codes_hauppauge_new);
+ break;
+ default:
+ /* unknown remote */
+ ir_input_init(input_dev, &budget_ci->ir.state,
+ IR_TYPE_RC5, ir_codes_budget_ci_old);
+ break;
+ }
+
+ /* initialise the key-up timeout handler */
+ input_dev->timer.function = msp430_ir_keyup;
+ input_dev->timer.data = (unsigned long) &budget_ci->ir;
+ input_dev->rep[REP_DELAY] = 1;
+ input_dev->rep[REP_PERIOD] = 1;
error = input_register_device(input_dev);
if (error) {
@@ -241,8 +259,6 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
goto out2;
}
- input_dev->timer.function = msp430_ir_debounce;
-
tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt,
(unsigned long) budget_ci);
@@ -267,7 +283,7 @@ static void msp430_ir_deinit(struct budget_ci *budget_ci)
tasklet_kill(&budget_ci->ir.msp430_irq_tasklet);
if (del_timer(&dev->timer)) {
- input_event(dev, EV_KEY, key_map[dev->repeat_key], 0);
+ ir_input_nokey(dev, &budget_ci->ir.state);
input_sync(dev);
}