aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/tm6000/tm6000-input.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/tm6000/tm6000-input.c')
-rw-r--r--drivers/media/video/tm6000/tm6000-input.c407
1 files changed, 224 insertions, 183 deletions
diff --git a/drivers/media/video/tm6000/tm6000-input.c b/drivers/media/video/tm6000/tm6000-input.c
index 405d12729d05..7844607dd45a 100644
--- a/drivers/media/video/tm6000/tm6000-input.c
+++ b/drivers/media/video/tm6000/tm6000-input.c
@@ -31,22 +31,25 @@
31 31
32static unsigned int ir_debug; 32static unsigned int ir_debug;
33module_param(ir_debug, int, 0644); 33module_param(ir_debug, int, 0644);
34MODULE_PARM_DESC(ir_debug, "enable debug message [IR]"); 34MODULE_PARM_DESC(ir_debug, "debug message level");
35 35
36static unsigned int enable_ir = 1; 36static unsigned int enable_ir = 1;
37module_param(enable_ir, int, 0644); 37module_param(enable_ir, int, 0644);
38MODULE_PARM_DESC(enable_ir, "enable ir (default is enable)"); 38MODULE_PARM_DESC(enable_ir, "enable ir (default is enable)");
39 39
40/* number of 50ms for ON-OFF-ON power led */ 40static unsigned int ir_clock_mhz = 12;
41/* show IR activity */ 41module_param(ir_clock_mhz, int, 0644);
42#define PWLED_OFF 2 42MODULE_PARM_DESC(enable_ir, "ir clock, in MHz");
43
44#define URB_SUBMIT_DELAY 100 /* ms - Delay to submit an URB request on retrial and init */
45#define URB_INT_LED_DELAY 100 /* ms - Delay to turn led on again on int mode */
43 46
44#undef dprintk 47#undef dprintk
45 48
46#define dprintk(fmt, arg...) \ 49#define dprintk(level, fmt, arg...) do {\
47 if (ir_debug) { \ 50 if (ir_debug >= level) \
48 printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \ 51 printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \
49 } 52 } while (0)
50 53
51struct tm6000_ir_poll_result { 54struct tm6000_ir_poll_result {
52 u16 rc_data; 55 u16 rc_data;
@@ -62,20 +65,15 @@ struct tm6000_IR {
62 int polling; 65 int polling;
63 struct delayed_work work; 66 struct delayed_work work;
64 u8 wait:1; 67 u8 wait:1;
65 u8 key:1; 68 u8 pwled:2;
66 u8 pwled:1; 69 u8 submit_urb:1;
67 u8 pwledcnt;
68 u16 key_addr; 70 u16 key_addr;
69 struct urb *int_urb; 71 struct urb *int_urb;
70 u8 *urb_data;
71
72 int (*get_key) (struct tm6000_IR *, struct tm6000_ir_poll_result *);
73 72
74 /* IR device properties */ 73 /* IR device properties */
75 u64 rc_type; 74 u64 rc_type;
76}; 75};
77 76
78
79void tm6000_ir_wait(struct tm6000_core *dev, u8 state) 77void tm6000_ir_wait(struct tm6000_core *dev, u8 state)
80{ 78{
81 struct tm6000_IR *ir = dev->ir; 79 struct tm6000_IR *ir = dev->ir;
@@ -83,62 +81,84 @@ void tm6000_ir_wait(struct tm6000_core *dev, u8 state)
83 if (!dev->ir) 81 if (!dev->ir)
84 return; 82 return;
85 83
84 dprintk(2, "%s: %i\n",__func__, ir->wait);
85
86 if (state) 86 if (state)
87 ir->wait = 1; 87 ir->wait = 1;
88 else 88 else
89 ir->wait = 0; 89 ir->wait = 0;
90} 90}
91 91
92
93static int tm6000_ir_config(struct tm6000_IR *ir) 92static int tm6000_ir_config(struct tm6000_IR *ir)
94{ 93{
95 struct tm6000_core *dev = ir->dev; 94 struct tm6000_core *dev = ir->dev;
96 u8 buf[10]; 95 u32 pulse = 0, leader = 0;
97 int rc; 96
97 dprintk(2, "%s\n",__func__);
98
99 /*
100 * The IR decoder supports RC-5 or NEC, with a configurable timing.
101 * The timing configuration there is not that accurate, as it uses
102 * approximate values. The NEC spec mentions a 562.5 unit period,
103 * and RC-5 uses a 888.8 period.
104 * Currently, driver assumes a clock provided by a 12 MHz XTAL, but
105 * a modprobe parameter can adjust it.
106 * Adjustments are required for other timings.
107 * It seems that the 900ms timing for NEC is used to detect a RC-5
108 * IR, in order to discard such decoding
109 */
98 110
99 switch (ir->rc_type) { 111 switch (ir->rc_type) {
100 case RC_TYPE_NEC: 112 case RC_TYPE_NEC:
101 /* Setup IR decoder for NEC standard 12MHz system clock */ 113 leader = 900; /* ms */
102 /* IR_LEADER_CNT = 0.9ms */ 114 pulse = 700; /* ms - the actual value would be 562 */
103 tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_LEADER1, 0xaa);
104 tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_LEADER0, 0x30);
105 /* IR_PULSE_CNT = 0.7ms */
106 tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_PULSE_CNT1, 0x20);
107 tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_PULSE_CNT0, 0xd0);
108 /* Remote WAKEUP = enable */
109 tm6000_set_reg(dev, TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe);
110 /* IR_WKUP_SEL = Low byte in decoded IR data */
111 tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_WAKEUP_SEL, 0xff);
112 /* IR_WKU_ADD code */
113 tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_WAKEUP_ADD, 0xff);
114 tm6000_flash_led(dev, 0);
115 msleep(100);
116 tm6000_flash_led(dev, 1);
117 break; 115 break;
118 default: 116 default:
119 /* hack */ 117 case RC_TYPE_RC5:
120 buf[0] = 0xff; 118 leader = 900; /* ms - from the NEC decoding */
121 buf[1] = 0xff; 119 pulse = 1780; /* ms - The actual value would be 1776 */
122 buf[2] = 0xf2;
123 buf[3] = 0x2b;
124 buf[4] = 0x20;
125 buf[5] = 0x35;
126 buf[6] = 0x60;
127 buf[7] = 0x04;
128 buf[8] = 0xc0;
129 buf[9] = 0x08;
130
131 rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR |
132 USB_RECIP_DEVICE, REQ_00_SET_IR_VALUE, 0, 0, buf, 0x0a);
133 msleep(100);
134
135 if (rc < 0) {
136 printk(KERN_INFO "IR configuration failed");
137 return rc;
138 }
139 break; 120 break;
140 } 121 }
141 122
123 pulse = ir_clock_mhz * pulse;
124 leader = ir_clock_mhz * leader;
125 if (ir->rc_type == RC_TYPE_NEC)
126 leader = leader | 0x8000;
127
128 dprintk(2, "%s: %s, %d MHz, leader = 0x%04x, pulse = 0x%06x \n",
129 __func__,
130 (ir->rc_type == RC_TYPE_NEC) ? "NEC" : "RC-5",
131 ir_clock_mhz, leader, pulse);
132
133 /* Remote WAKEUP = enable, normal mode, from IR decoder output */
134 tm6000_set_reg(dev, TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe);
135
136 /* Enable IR reception on non-busrt mode */
137 tm6000_set_reg(dev, TM6010_REQ07_RD8_IR, 0x2f);
138
139 /* IR_WKUP_SEL = Low byte in decoded IR data */
140 tm6000_set_reg(dev, TM6010_REQ07_RDA_IR_WAKEUP_SEL, 0xff);
141 /* IR_WKU_ADD code */
142 tm6000_set_reg(dev, TM6010_REQ07_RDB_IR_WAKEUP_ADD, 0xff);
143
144 tm6000_set_reg(dev, TM6010_REQ07_RDC_IR_LEADER1, leader >> 8);
145 tm6000_set_reg(dev, TM6010_REQ07_RDD_IR_LEADER0, leader);
146
147 tm6000_set_reg(dev, TM6010_REQ07_RDE_IR_PULSE_CNT1, pulse >> 8);
148 tm6000_set_reg(dev, TM6010_REQ07_RDF_IR_PULSE_CNT0, pulse);
149
150 if (!ir->polling)
151 tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0);
152 else
153 tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 1);
154 msleep(10);
155
156 /* Shows that IR is working via the LED */
157 tm6000_flash_led(dev, 0);
158 msleep(100);
159 tm6000_flash_led(dev, 1);
160 ir->pwled = 1;
161
142 return 0; 162 return 0;
143} 163}
144 164
@@ -146,132 +166,124 @@ static void tm6000_ir_urb_received(struct urb *urb)
146{ 166{
147 struct tm6000_core *dev = urb->context; 167 struct tm6000_core *dev = urb->context;
148 struct tm6000_IR *ir = dev->ir; 168 struct tm6000_IR *ir = dev->ir;
169 struct tm6000_ir_poll_result poll_result;
170 char *buf;
149 int rc; 171 int rc;
150 172
151 if (urb->status != 0) 173 dprintk(2, "%s\n",__func__);
152 printk(KERN_INFO "not ready\n"); 174 if (urb->status < 0 || urb->actual_length <= 0) {
153 else if (urb->actual_length > 0) { 175 printk(KERN_INFO "tm6000: IR URB failure: status: %i, length %i\n",
154 memcpy(ir->urb_data, urb->transfer_buffer, urb->actual_length); 176 urb->status, urb->actual_length);
177 ir->submit_urb = 1;
178 schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_SUBMIT_DELAY));
179 return;
180 }
181 buf = urb->transfer_buffer;
155 182
156 dprintk("data %02x %02x %02x %02x\n", ir->urb_data[0], 183 if (ir_debug)
157 ir->urb_data[1], ir->urb_data[2], ir->urb_data[3]); 184 print_hex_dump(KERN_DEBUG, "tm6000: IR data: ",
185 DUMP_PREFIX_OFFSET,16, 1,
186 buf, urb->actual_length, false);
158 187
159 ir->key = 1; 188 poll_result.rc_data = buf[0];
160 } 189 if (urb->actual_length > 1)
190 poll_result.rc_data |= buf[1] << 8;
191
192 dprintk(1, "%s, scancode: 0x%04x\n",__func__, poll_result.rc_data);
193 rc_keydown(ir->rc, poll_result.rc_data, 0);
161 194
162 rc = usb_submit_urb(urb, GFP_ATOMIC); 195 rc = usb_submit_urb(urb, GFP_ATOMIC);
196 /*
197 * Flash the led. We can't do it here, as it is running on IRQ context.
198 * So, use the scheduler to do it, in a few ms.
199 */
200 ir->pwled = 2;
201 schedule_delayed_work(&ir->work, msecs_to_jiffies(10));
163} 202}
164 203
165static int default_polling_getkey(struct tm6000_IR *ir, 204static void tm6000_ir_handle_key(struct work_struct *work)
166 struct tm6000_ir_poll_result *poll_result)
167{ 205{
206 struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work);
168 struct tm6000_core *dev = ir->dev; 207 struct tm6000_core *dev = ir->dev;
208 struct tm6000_ir_poll_result poll_result;
169 int rc; 209 int rc;
170 u8 buf[2]; 210 u8 buf[2];
171 211
172 if (ir->wait && !&dev->int_in) 212 if (ir->wait)
173 return 0; 213 return;
174
175 if (&dev->int_in) {
176 switch (ir->rc_type) {
177 case RC_TYPE_RC5:
178 poll_result->rc_data = ir->urb_data[0];
179 break;
180 case RC_TYPE_NEC:
181 if (ir->urb_data[1] == ((ir->key_addr >> 8) & 0xff)) {
182 poll_result->rc_data = ir->urb_data[0]
183 | ir->urb_data[1] << 8;
184 }
185 break;
186 default:
187 poll_result->rc_data = ir->urb_data[0]
188 | ir->urb_data[1] << 8;
189 break;
190 }
191 } else {
192 tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0);
193 msleep(10);
194 tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 1);
195 msleep(10);
196
197 if (ir->rc_type == RC_TYPE_RC5) {
198 rc = tm6000_read_write_usb(dev, USB_DIR_IN |
199 USB_TYPE_VENDOR | USB_RECIP_DEVICE,
200 REQ_02_GET_IR_CODE, 0, 0, buf, 1);
201
202 msleep(10);
203
204 dprintk("read data=%02x\n", buf[0]);
205 if (rc < 0)
206 return rc;
207 214
208 poll_result->rc_data = buf[0]; 215 dprintk(3, "%s\n",__func__);
209 } else {
210 rc = tm6000_read_write_usb(dev, USB_DIR_IN |
211 USB_TYPE_VENDOR | USB_RECIP_DEVICE,
212 REQ_02_GET_IR_CODE, 0, 0, buf, 2);
213 216
214 msleep(10); 217 rc = tm6000_read_write_usb(dev, USB_DIR_IN |
218 USB_TYPE_VENDOR | USB_RECIP_DEVICE,
219 REQ_02_GET_IR_CODE, 0, 0, buf, 2);
220 if (rc < 0)
221 return;
215 222
216 dprintk("read data=%04x\n", buf[0] | buf[1] << 8); 223 if (rc > 1)
217 if (rc < 0) 224 poll_result.rc_data = buf[0] | buf[1] << 8;
218 return rc; 225 else
226 poll_result.rc_data = buf[0];
219 227
220 poll_result->rc_data = buf[0] | buf[1] << 8; 228 /* Check if something was read */
229 if ((poll_result.rc_data & 0xff) == 0xff) {
230 if (!ir->pwled) {
231 tm6000_flash_led(dev, 1);
232 ir->pwled = 1;
221 } 233 }
222 if ((poll_result->rc_data & 0x00ff) != 0xff) 234 return;
223 ir->key = 1;
224 } 235 }
225 return 0; 236
237 dprintk(1, "%s, scancode: 0x%04x\n",__func__, poll_result.rc_data);
238 rc_keydown(ir->rc, poll_result.rc_data, 0);
239 tm6000_flash_led(dev, 0);
240 ir->pwled = 0;
241
242 /* Re-schedule polling */
243 schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling));
226} 244}
227 245
228static void tm6000_ir_handle_key(struct tm6000_IR *ir) 246static void tm6000_ir_int_work(struct work_struct *work)
229{ 247{
248 struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work);
230 struct tm6000_core *dev = ir->dev; 249 struct tm6000_core *dev = ir->dev;
231 int result; 250 int rc;
232 struct tm6000_ir_poll_result poll_result;
233 251
234 /* read the registers containing the IR status */ 252 dprintk(3, "%s, submit_urb = %d, pwled = %d\n",__func__, ir->submit_urb,
235 result = ir->get_key(ir, &poll_result); 253 ir->pwled);
236 if (result < 0) {
237 printk(KERN_INFO "ir->get_key() failed %d\n", result);
238 return;
239 }
240 254
241 dprintk("ir->get_key result data=%04x\n", poll_result.rc_data); 255 if (ir->submit_urb) {
256 dprintk(3, "Resubmit urb\n");
257 tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0);
242 258
243 if (ir->pwled) { 259 rc = usb_submit_urb(ir->int_urb, GFP_ATOMIC);
244 if (ir->pwledcnt >= PWLED_OFF) { 260 if (rc < 0) {
245 ir->pwled = 0; 261 printk(KERN_ERR "tm6000: Can't submit an IR interrupt. Error %i\n",
246 ir->pwledcnt = 0; 262 rc);
247 tm6000_flash_led(dev, 1); 263 /* Retry in 100 ms */
248 } else 264 schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_SUBMIT_DELAY));
249 ir->pwledcnt += 1; 265 return;
266 }
267 ir->submit_urb = 0;
250 } 268 }
251 269
252 if (ir->key) { 270 /* Led is enabled only if USB submit doesn't fail */
253 rc_keydown(ir->rc, poll_result.rc_data, 0); 271 if (ir->pwled == 2) {
254 ir->key = 0;
255 ir->pwled = 1;
256 ir->pwledcnt = 0;
257 tm6000_flash_led(dev, 0); 272 tm6000_flash_led(dev, 0);
273 ir->pwled = 0;
274 schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_INT_LED_DELAY));
275 } else if (!ir->pwled) {
276 tm6000_flash_led(dev, 1);
277 ir->pwled = 1;
258 } 278 }
259 return;
260}
261
262static void tm6000_ir_work(struct work_struct *work)
263{
264 struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work);
265
266 tm6000_ir_handle_key(ir);
267 schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling));
268} 279}
269 280
270static int tm6000_ir_start(struct rc_dev *rc) 281static int tm6000_ir_start(struct rc_dev *rc)
271{ 282{
272 struct tm6000_IR *ir = rc->priv; 283 struct tm6000_IR *ir = rc->priv;
273 284
274 INIT_DELAYED_WORK(&ir->work, tm6000_ir_work); 285 dprintk(2, "%s\n",__func__);
286
275 schedule_delayed_work(&ir->work, 0); 287 schedule_delayed_work(&ir->work, 0);
276 288
277 return 0; 289 return 0;
@@ -281,6 +293,8 @@ static void tm6000_ir_stop(struct rc_dev *rc)
281{ 293{
282 struct tm6000_IR *ir = rc->priv; 294 struct tm6000_IR *ir = rc->priv;
283 295
296 dprintk(2, "%s\n",__func__);
297
284 cancel_delayed_work_sync(&ir->work); 298 cancel_delayed_work_sync(&ir->work);
285} 299}
286 300
@@ -291,10 +305,11 @@ static int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
291 if (!ir) 305 if (!ir)
292 return 0; 306 return 0;
293 307
308 dprintk(2, "%s\n",__func__);
309
294 if ((rc->rc_map.scan) && (rc_type == RC_TYPE_NEC)) 310 if ((rc->rc_map.scan) && (rc_type == RC_TYPE_NEC))
295 ir->key_addr = ((rc->rc_map.scan[0].scancode >> 8) & 0xffff); 311 ir->key_addr = ((rc->rc_map.scan[0].scancode >> 8) & 0xffff);
296 312
297 ir->get_key = default_polling_getkey;
298 ir->rc_type = rc_type; 313 ir->rc_type = rc_type;
299 314
300 tm6000_ir_config(ir); 315 tm6000_ir_config(ir);
@@ -302,17 +317,19 @@ static int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
302 return 0; 317 return 0;
303} 318}
304 319
305int tm6000_ir_int_start(struct tm6000_core *dev) 320static int __tm6000_ir_int_start(struct rc_dev *rc)
306{ 321{
307 struct tm6000_IR *ir = dev->ir; 322 struct tm6000_IR *ir = rc->priv;
323 struct tm6000_core *dev = ir->dev;
308 int pipe, size; 324 int pipe, size;
309 int err = -ENOMEM; 325 int err = -ENOMEM;
310 326
311
312 if (!ir) 327 if (!ir)
313 return -ENODEV; 328 return -ENODEV;
314 329
315 ir->int_urb = usb_alloc_urb(0, GFP_KERNEL); 330 dprintk(2, "%s\n",__func__);
331
332 ir->int_urb = usb_alloc_urb(0, GFP_ATOMIC);
316 if (!ir->int_urb) 333 if (!ir->int_urb)
317 return -ENOMEM; 334 return -ENOMEM;
318 335
@@ -321,42 +338,59 @@ int tm6000_ir_int_start(struct tm6000_core *dev)
321 & USB_ENDPOINT_NUMBER_MASK); 338 & USB_ENDPOINT_NUMBER_MASK);
322 339
323 size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe)); 340 size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe));
324 dprintk("IR max size: %d\n", size); 341 dprintk(1, "IR max size: %d\n", size);
325 342
326 ir->int_urb->transfer_buffer = kzalloc(size, GFP_KERNEL); 343 ir->int_urb->transfer_buffer = kzalloc(size, GFP_ATOMIC);
327 if (ir->int_urb->transfer_buffer == NULL) { 344 if (ir->int_urb->transfer_buffer == NULL) {
328 usb_free_urb(ir->int_urb); 345 usb_free_urb(ir->int_urb);
329 return err; 346 return err;
330 } 347 }
331 dprintk("int interval: %d\n", dev->int_in.endp->desc.bInterval); 348 dprintk(1, "int interval: %d\n", dev->int_in.endp->desc.bInterval);
349
332 usb_fill_int_urb(ir->int_urb, dev->udev, pipe, 350 usb_fill_int_urb(ir->int_urb, dev->udev, pipe,
333 ir->int_urb->transfer_buffer, size, 351 ir->int_urb->transfer_buffer, size,
334 tm6000_ir_urb_received, dev, 352 tm6000_ir_urb_received, dev,
335 dev->int_in.endp->desc.bInterval); 353 dev->int_in.endp->desc.bInterval);
336 err = usb_submit_urb(ir->int_urb, GFP_KERNEL); 354
337 if (err) { 355 ir->submit_urb = 1;
338 kfree(ir->int_urb->transfer_buffer); 356 schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_SUBMIT_DELAY));
339 usb_free_urb(ir->int_urb);
340 return err;
341 }
342 ir->urb_data = kzalloc(size, GFP_KERNEL);
343 357
344 return 0; 358 return 0;
345} 359}
346 360
347void tm6000_ir_int_stop(struct tm6000_core *dev) 361static void __tm6000_ir_int_stop(struct rc_dev *rc)
348{ 362{
349 struct tm6000_IR *ir = dev->ir; 363 struct tm6000_IR *ir = rc->priv;
350 364
351 if (!ir) 365 if (!ir || !ir->int_urb)
352 return; 366 return;
353 367
368 dprintk(2, "%s\n",__func__);
369
354 usb_kill_urb(ir->int_urb); 370 usb_kill_urb(ir->int_urb);
355 kfree(ir->int_urb->transfer_buffer); 371 kfree(ir->int_urb->transfer_buffer);
356 usb_free_urb(ir->int_urb); 372 usb_free_urb(ir->int_urb);
357 ir->int_urb = NULL; 373 ir->int_urb = NULL;
358 kfree(ir->urb_data); 374}
359 ir->urb_data = NULL; 375
376int tm6000_ir_int_start(struct tm6000_core *dev)
377{
378 struct tm6000_IR *ir = dev->ir;
379
380 if (!ir)
381 return 0;
382
383 return __tm6000_ir_int_start(ir->rc);
384}
385
386void tm6000_ir_int_stop(struct tm6000_core *dev)
387{
388 struct tm6000_IR *ir = dev->ir;
389
390 if (!ir || !ir->rc)
391 return;
392
393 __tm6000_ir_int_stop(ir->rc);
360} 394}
361 395
362int tm6000_ir_init(struct tm6000_core *dev) 396int tm6000_ir_init(struct tm6000_core *dev)
@@ -374,29 +408,36 @@ int tm6000_ir_init(struct tm6000_core *dev)
374 if (!dev->ir_codes) 408 if (!dev->ir_codes)
375 return 0; 409 return 0;
376 410
377 ir = kzalloc(sizeof(*ir), GFP_KERNEL); 411 ir = kzalloc(sizeof(*ir), GFP_ATOMIC);
378 rc = rc_allocate_device(); 412 rc = rc_allocate_device();
379 if (!ir || !rc) 413 if (!ir || !rc)
380 goto out; 414 goto out;
381 415
416 dprintk(2, "%s\n", __func__);
417
382 /* record handles to ourself */ 418 /* record handles to ourself */
383 ir->dev = dev; 419 ir->dev = dev;
384 dev->ir = ir; 420 dev->ir = ir;
385 ir->rc = rc; 421 ir->rc = rc;
386 422
387 /* input einrichten */ 423 /* input setup */
388 rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC; 424 rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC;
425 /* Neded, in order to support NEC remotes with 24 or 32 bits */
426 rc->scanmask = 0xffff;
389 rc->priv = ir; 427 rc->priv = ir;
390 rc->change_protocol = tm6000_ir_change_protocol; 428 rc->change_protocol = tm6000_ir_change_protocol;
391 rc->open = tm6000_ir_start; 429 if (dev->int_in.endp) {
392 rc->close = tm6000_ir_stop; 430 rc->open = __tm6000_ir_int_start;
431 rc->close = __tm6000_ir_int_stop;
432 INIT_DELAYED_WORK(&ir->work, tm6000_ir_int_work);
433 } else {
434 rc->open = tm6000_ir_start;
435 rc->close = tm6000_ir_stop;
436 ir->polling = 50;
437 INIT_DELAYED_WORK(&ir->work, tm6000_ir_handle_key);
438 }
393 rc->driver_type = RC_DRIVER_SCANCODE; 439 rc->driver_type = RC_DRIVER_SCANCODE;
394 440
395 ir->polling = 50;
396 ir->pwled = 0;
397 ir->pwledcnt = 0;
398
399
400 snprintf(ir->name, sizeof(ir->name), "tm5600/60x0 IR (%s)", 441 snprintf(ir->name, sizeof(ir->name), "tm5600/60x0 IR (%s)",
401 dev->name); 442 dev->name);
402 443
@@ -415,15 +456,6 @@ int tm6000_ir_init(struct tm6000_core *dev)
415 rc->driver_name = "tm6000"; 456 rc->driver_name = "tm6000";
416 rc->dev.parent = &dev->udev->dev; 457 rc->dev.parent = &dev->udev->dev;
417 458
418 if (&dev->int_in) {
419 dprintk("IR over int\n");
420
421 err = tm6000_ir_int_start(dev);
422
423 if (err)
424 goto out;
425 }
426
427 /* ir register */ 459 /* ir register */
428 err = rc_register_device(rc); 460 err = rc_register_device(rc);
429 if (err) 461 if (err)
@@ -447,10 +479,19 @@ int tm6000_ir_fini(struct tm6000_core *dev)
447 if (!ir) 479 if (!ir)
448 return 0; 480 return 0;
449 481
482 dprintk(2, "%s\n",__func__);
483
450 rc_unregister_device(ir->rc); 484 rc_unregister_device(ir->rc);
451 485
452 if (ir->int_urb) 486 if (!ir->polling)
453 tm6000_ir_int_stop(dev); 487 __tm6000_ir_int_stop(ir->rc);
488
489 tm6000_ir_stop(ir->rc);
490
491 /* Turn off the led */
492 tm6000_flash_led(dev, 0);
493 ir->pwled = 0;
494
454 495
455 kfree(ir); 496 kfree(ir);
456 dev->ir = NULL; 497 dev->ir = NULL;