diff options
Diffstat (limited to 'drivers/media/dvb/ttpci/budget-ci.c')
-rw-r--r-- | drivers/media/dvb/ttpci/budget-ci.c | 138 |
1 files changed, 77 insertions, 61 deletions
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index c34b5d3bdde5..d1b5402cd6fe 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/interrupt.h> | 37 | #include <linux/interrupt.h> |
38 | #include <linux/input.h> | 38 | #include <linux/input.h> |
39 | #include <linux/spinlock.h> | 39 | #include <linux/spinlock.h> |
40 | #include <media/ir-common.h> | ||
40 | 41 | ||
41 | #include "dvb_ca_en50221.h" | 42 | #include "dvb_ca_en50221.h" |
42 | #include "stv0299.h" | 43 | #include "stv0299.h" |
@@ -72,11 +73,24 @@ | |||
72 | #define SLOTSTATUS_READY 8 | 73 | #define SLOTSTATUS_READY 8 |
73 | #define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY) | 74 | #define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY) |
74 | 75 | ||
76 | /* Milliseconds during which key presses are regarded as key repeat and during | ||
77 | * which the debounce logic is active | ||
78 | */ | ||
79 | #define IR_REPEAT_TIMEOUT 350 | ||
80 | |||
81 | /* Some remotes sends multiple sequences per keypress (e.g. Zenith sends two), | ||
82 | * this setting allows the superflous sequences to be ignored | ||
83 | */ | ||
84 | static int debounce = 0; | ||
85 | module_param(debounce, int, 0644); | ||
86 | MODULE_PARM_DESC(debounce, "ignore repeated IR sequences (default: 0 = ignore no sequences)"); | ||
87 | |||
75 | struct budget_ci_ir { | 88 | struct budget_ci_ir { |
76 | struct input_dev *dev; | 89 | struct input_dev *dev; |
77 | struct tasklet_struct msp430_irq_tasklet; | 90 | struct tasklet_struct msp430_irq_tasklet; |
78 | char name[72]; /* 40 + 32 for (struct saa7146_dev).name */ | 91 | char name[72]; /* 40 + 32 for (struct saa7146_dev).name */ |
79 | char phys[32]; | 92 | char phys[32]; |
93 | struct ir_input_state state; | ||
80 | }; | 94 | }; |
81 | 95 | ||
82 | struct budget_ci { | 96 | struct budget_ci { |
@@ -89,59 +103,44 @@ struct budget_ci { | |||
89 | u8 tuner_pll_address; /* used for philips_tdm1316l configs */ | 103 | u8 tuner_pll_address; /* used for philips_tdm1316l configs */ |
90 | }; | 104 | }; |
91 | 105 | ||
92 | /* from reading the following remotes: | 106 | static void msp430_ir_keyup(unsigned long data) |
93 | Zenith Universal 7 / TV Mode 807 / VCR Mode 837 | 107 | { |
94 | Hauppauge (from NOVA-CI-s box product) | 108 | struct budget_ci_ir *ir = (struct budget_ci_ir *) data; |
95 | i've taken a "middle of the road" approach and note the differences | 109 | ir_input_nokey(ir->dev, &ir->state); |
96 | */ | 110 | } |
97 | static u16 key_map[64] = { | 111 | |
98 | /* 0x0X */ | 112 | static void msp430_ir_interrupt(unsigned long data) |
99 | KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, | 113 | { |
100 | KEY_9, | 114 | struct budget_ci *budget_ci = (struct budget_ci *) data; |
101 | KEY_ENTER, | 115 | struct input_dev *dev = budget_ci->ir.dev; |
102 | KEY_RED, | 116 | static int bounces = 0; |
103 | KEY_POWER, /* RADIO on Hauppauge */ | 117 | u32 ir_key; |
104 | KEY_MUTE, | 118 | u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8; |
105 | 0, | 119 | |
106 | KEY_A, /* TV on Hauppauge */ | 120 | if (command & 0x40) { |
107 | /* 0x1X */ | 121 | ir_key = command & 0x3f; |
108 | KEY_VOLUMEUP, KEY_VOLUMEDOWN, | 122 | |
109 | 0, 0, | 123 | if (ir_key != dev->repeat_key && del_timer(&dev->timer)) |
110 | KEY_B, | 124 | /* We were still waiting for a keyup event but this is a new key */ |
111 | 0, 0, 0, 0, 0, 0, 0, | 125 | ir_input_nokey(dev, &budget_ci->ir.state); |
112 | KEY_UP, KEY_DOWN, | 126 | |
113 | KEY_OPTION, /* RESERVED on Hauppauge */ | 127 | if (ir_key == dev->repeat_key && bounces > 0 && timer_pending(&dev->timer)) { |
114 | KEY_BREAK, | 128 | /* Ignore repeated key sequences if requested */ |
115 | /* 0x2X */ | 129 | bounces--; |
116 | KEY_CHANNELUP, KEY_CHANNELDOWN, | 130 | return; |
117 | KEY_PREVIOUS, /* Prev. Ch on Zenith, SOURCE on Hauppauge */ | 131 | } |
118 | 0, KEY_RESTART, KEY_OK, | 132 | |
119 | KEY_CYCLEWINDOWS, /* MINIMIZE on Hauppauge */ | 133 | if (!timer_pending(&dev->timer)) |
120 | 0, | 134 | /* New keypress */ |
121 | KEY_ENTER, /* VCR mode on Zenith */ | 135 | bounces = debounce; |
122 | KEY_PAUSE, | 136 | |
123 | 0, | 137 | /* Prepare a keyup event sometime in the future */ |
124 | KEY_RIGHT, KEY_LEFT, | 138 | mod_timer(&dev->timer, jiffies + msecs_to_jiffies(IR_REPEAT_TIMEOUT)); |
125 | 0, | 139 | |
126 | KEY_MENU, /* FULL SCREEN on Hauppauge */ | 140 | /* Generate a new or repeated keypress */ |
127 | 0, | 141 | ir_input_keydown(dev, &budget_ci->ir.state, ir_key, command); |
128 | /* 0x3X */ | 142 | } |
129 | KEY_SLOW, | 143 | } |
130 | KEY_PREVIOUS, /* VCR mode on Zenith */ | ||
131 | KEY_REWIND, | ||
132 | 0, | ||
133 | KEY_FASTFORWARD, | ||
134 | KEY_PLAY, KEY_STOP, | ||
135 | KEY_RECORD, | ||
136 | KEY_TUNER, /* TV/VCR on Zenith */ | ||
137 | 0, | ||
138 | KEY_C, | ||
139 | 0, | ||
140 | KEY_EXIT, | ||
141 | KEY_POWER2, | ||
142 | KEY_TUNER, /* VCR mode on Zenith */ | ||
143 | 0, | ||
144 | }; | ||
145 | 144 | ||
146 | static void msp430_ir_debounce(unsigned long data) | 145 | static void msp430_ir_debounce(unsigned long data) |
147 | { | 146 | { |
@@ -197,7 +196,6 @@ static int msp430_ir_init(struct budget_ci *budget_ci) | |||
197 | { | 196 | { |
198 | struct saa7146_dev *saa = budget_ci->budget.dev; | 197 | struct saa7146_dev *saa = budget_ci->budget.dev; |
199 | struct input_dev *input_dev = budget_ci->ir.dev; | 198 | struct input_dev *input_dev = budget_ci->ir.dev; |
200 | int i; | ||
201 | int error; | 199 | int error; |
202 | 200 | ||
203 | budget_ci->ir.dev = input_dev = input_allocate_device(); | 201 | budget_ci->ir.dev = input_dev = input_allocate_device(); |
@@ -230,10 +228,30 @@ static int msp430_ir_init(struct budget_ci *budget_ci) | |||
230 | input_dev->dev = &saa->pci->dev; | 228 | input_dev->dev = &saa->pci->dev; |
231 | # endif | 229 | # endif |
232 | 230 | ||
233 | set_bit(EV_KEY, input_dev->evbit); | 231 | /* Select keymap */ |
234 | for (i = 0; i < ARRAY_SIZE(key_map); i++) | 232 | switch (budget_ci->budget.dev->pci->subsystem_device) { |
235 | if (key_map[i]) | 233 | case 0x100c: |
236 | set_bit(key_map[i], input_dev->keybit); | 234 | case 0x100f: |
235 | case 0x1010: | ||
236 | case 0x1011: | ||
237 | case 0x1012: | ||
238 | case 0x1017: | ||
239 | /* The hauppauge keymap is a superset of these remotes */ | ||
240 | ir_input_init(input_dev, &budget_ci->ir.state, | ||
241 | IR_TYPE_RC5, ir_codes_hauppauge_new); | ||
242 | break; | ||
243 | default: | ||
244 | /* unknown remote */ | ||
245 | ir_input_init(input_dev, &budget_ci->ir.state, | ||
246 | IR_TYPE_RC5, ir_codes_budget_ci_old); | ||
247 | break; | ||
248 | } | ||
249 | |||
250 | /* initialise the key-up timeout handler */ | ||
251 | input_dev->timer.function = msp430_ir_keyup; | ||
252 | input_dev->timer.data = (unsigned long) &budget_ci->ir; | ||
253 | input_dev->rep[REP_DELAY] = 1; | ||
254 | input_dev->rep[REP_PERIOD] = 1; | ||
237 | 255 | ||
238 | error = input_register_device(input_dev); | 256 | error = input_register_device(input_dev); |
239 | if (error) { | 257 | if (error) { |
@@ -241,8 +259,6 @@ static int msp430_ir_init(struct budget_ci *budget_ci) | |||
241 | goto out2; | 259 | goto out2; |
242 | } | 260 | } |
243 | 261 | ||
244 | input_dev->timer.function = msp430_ir_debounce; | ||
245 | |||
246 | tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt, | 262 | tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt, |
247 | (unsigned long) budget_ci); | 263 | (unsigned long) budget_ci); |
248 | 264 | ||
@@ -267,7 +283,7 @@ static void msp430_ir_deinit(struct budget_ci *budget_ci) | |||
267 | tasklet_kill(&budget_ci->ir.msp430_irq_tasklet); | 283 | tasklet_kill(&budget_ci->ir.msp430_irq_tasklet); |
268 | 284 | ||
269 | if (del_timer(&dev->timer)) { | 285 | if (del_timer(&dev->timer)) { |
270 | input_event(dev, EV_KEY, key_map[dev->repeat_key], 0); | 286 | ir_input_nokey(dev, &budget_ci->ir.state); |
271 | input_sync(dev); | 287 | input_sync(dev); |
272 | } | 288 | } |
273 | 289 | ||