aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitri Belimov <d.belimov@gmail.com>2010-12-22 03:57:46 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-12-29 05:17:15 -0500
commit641d21167f66ef4c574ef4f586fec0ae32179acd (patch)
treea9c2fe5ed8d53a1a0aaf1dbb760c3cf076c4cf49
parentdb9285f79b12286a3b525b41ab275796679c1dfa (diff)
[media] tm6000: rework and fix IR
Hi This patch didn't kill Stefan's remotes and just for upload my good part of code. 1. Add some code for show IR activity 2. Add filter for IR remotes 3. Split remotes to different types. 4. Fix stop interrupt pipe when isoc pipe started. When we decide general way of IR I'll add support our remotes. For our customers I'll made custom temporary patch without this part. Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/staging/tm6000/TODO2
-rw-r--r--drivers/staging/tm6000/tm6000-cards.c41
-rw-r--r--drivers/staging/tm6000/tm6000-input.c197
-rw-r--r--drivers/staging/tm6000/tm6000-video.c5
-rw-r--r--drivers/staging/tm6000/tm6000.h3
5 files changed, 195 insertions, 53 deletions
diff --git a/drivers/staging/tm6000/TODO b/drivers/staging/tm6000/TODO
index 34780fc17b16..135d0ea3ad70 100644
--- a/drivers/staging/tm6000/TODO
+++ b/drivers/staging/tm6000/TODO
@@ -1,4 +1,6 @@
1There a few things to do before putting this driver in production: 1There a few things to do before putting this driver in production:
2 - IR NEC with tm5600/6000 TV cards
3 - IR RC5 with tm5600/6000/6010 TV cards
2 - CodingStyle; 4 - CodingStyle;
3 - Fix audio; 5 - Fix audio;
4 - Fix some panic/OOPS conditions. 6 - Fix some panic/OOPS conditions.
diff --git a/drivers/staging/tm6000/tm6000-cards.c b/drivers/staging/tm6000/tm6000-cards.c
index 5a7946c6de50..455038bdfc9f 100644
--- a/drivers/staging/tm6000/tm6000-cards.c
+++ b/drivers/staging/tm6000/tm6000-cards.c
@@ -328,6 +328,47 @@ struct usb_device_id tm6000_id_table[] = {
328 { }, 328 { },
329}; 329};
330 330
331/* Control power led for show some activity */
332void tm6000_flash_led(struct tm6000_core *dev, u8 state)
333{
334 /* Power LED unconfigured */
335 if (!dev->gpio.power_led)
336 return;
337
338 /* ON Power LED */
339 if (state) {
340 switch (dev->model) {
341 case TM6010_BOARD_HAUPPAUGE_900H:
342 case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
343 case TM6010_BOARD_TWINHAN_TU501:
344 tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
345 dev->gpio.power_led, 0x00);
346 break;
347 case TM6010_BOARD_BEHOLD_WANDER:
348 case TM6010_BOARD_BEHOLD_VOYAGER:
349 tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
350 dev->gpio.power_led, 0x01);
351 break;
352 }
353 }
354 /* OFF Power LED */
355 else {
356 switch (dev->model) {
357 case TM6010_BOARD_HAUPPAUGE_900H:
358 case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
359 case TM6010_BOARD_TWINHAN_TU501:
360 tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
361 dev->gpio.power_led, 0x01);
362 break;
363 case TM6010_BOARD_BEHOLD_WANDER:
364 case TM6010_BOARD_BEHOLD_VOYAGER:
365 tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
366 dev->gpio.power_led, 0x00);
367 break;
368 }
369 }
370}
371
331/* Tuner callback to provide the proper gpio changes needed for xc5000 */ 372/* Tuner callback to provide the proper gpio changes needed for xc5000 */
332int tm6000_xc5000_callback(void *ptr, int component, int command, int arg) 373int tm6000_xc5000_callback(void *ptr, int component, int command, int arg)
333{ 374{
diff --git a/drivers/staging/tm6000/tm6000-input.c b/drivers/staging/tm6000/tm6000-input.c
index e02ea6720380..21e7da40f049 100644
--- a/drivers/staging/tm6000/tm6000-input.c
+++ b/drivers/staging/tm6000/tm6000-input.c
@@ -37,6 +37,10 @@ static 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 */
41/* show IR activity */
42#define PWLED_OFF 2
43
40#undef dprintk 44#undef dprintk
41 45
42#define dprintk(fmt, arg...) \ 46#define dprintk(fmt, arg...) \
@@ -59,6 +63,9 @@ struct tm6000_IR {
59 struct delayed_work work; 63 struct delayed_work work;
60 u8 wait:1; 64 u8 wait:1;
61 u8 key:1; 65 u8 key:1;
66 u8 pwled:1;
67 u8 pwledcnt;
68 u16 key_addr;
62 struct urb *int_urb; 69 struct urb *int_urb;
63 u8 *urb_data; 70 u8 *urb_data;
64 71
@@ -89,26 +96,49 @@ static int tm6000_ir_config(struct tm6000_IR *ir)
89 u8 buf[10]; 96 u8 buf[10];
90 int rc; 97 int rc;
91 98
92 /* hack */ 99 switch (ir->rc_type) {
93 buf[0] = 0xff; 100 case RC_TYPE_NEC:
94 buf[1] = 0xff; 101 /* Setup IR decoder for NEC standard 12MHz system clock */
95 buf[2] = 0xf2; 102 /* IR_LEADER_CNT = 0.9ms */
96 buf[3] = 0x2b; 103 tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_LEADER1, 0xaa);
97 buf[4] = 0x20; 104 tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_LEADER0, 0x30);
98 buf[5] = 0x35; 105 /* IR_PULSE_CNT = 0.7ms */
99 buf[6] = 0x60; 106 tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_PULSE_CNT1, 0x20);
100 buf[7] = 0x04; 107 tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_PULSE_CNT0, 0xd0);
101 buf[8] = 0xc0; 108 /* Remote WAKEUP = enable */
102 buf[9] = 0x08; 109 tm6000_set_reg(dev, TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe);
103 110 /* IR_WKUP_SEL = Low byte in decoded IR data */
104 rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR | 111 tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_WAKEUP_SEL, 0xff);
105 USB_RECIP_DEVICE, REQ_00_SET_IR_VALUE, 0, 0, buf, 0x0a); 112 /* IR_WKU_ADD code */
106 msleep(100); 113 tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_WAKEUP_ADD, 0xff);
107 114 tm6000_flash_led(dev, 0);
108 if (rc < 0) { 115 msleep(100);
109 printk(KERN_INFO "IR configuration failed"); 116 tm6000_flash_led(dev, 1);
110 return rc; 117 break;
118 default:
119 /* hack */
120 buf[0] = 0xff;
121 buf[1] = 0xff;
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;
111 } 140 }
141
112 return 0; 142 return 0;
113} 143}
114 144
@@ -143,10 +173,21 @@ static int default_polling_getkey(struct tm6000_IR *ir,
143 return 0; 173 return 0;
144 174
145 if (&dev->int_in) { 175 if (&dev->int_in) {
146 if (ir->rc_type == RC_TYPE_RC5) 176 switch (ir->rc_type) {
177 case RC_TYPE_RC5:
147 poll_result->rc_data = ir->urb_data[0]; 178 poll_result->rc_data = ir->urb_data[0];
148 else 179 break;
149 poll_result->rc_data = ir->urb_data[0] | ir->urb_data[1] << 8; 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 }
150 } else { 191 } else {
151 tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0); 192 tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0);
152 msleep(10); 193 msleep(10);
@@ -186,6 +227,7 @@ static int default_polling_getkey(struct tm6000_IR *ir,
186 227
187static void tm6000_ir_handle_key(struct tm6000_IR *ir) 228static void tm6000_ir_handle_key(struct tm6000_IR *ir)
188{ 229{
230 struct tm6000_core *dev = ir->dev;
189 int result; 231 int result;
190 struct tm6000_ir_poll_result poll_result; 232 struct tm6000_ir_poll_result poll_result;
191 233
@@ -198,9 +240,21 @@ static void tm6000_ir_handle_key(struct tm6000_IR *ir)
198 240
199 dprintk("ir->get_key result data=%04x\n", poll_result.rc_data); 241 dprintk("ir->get_key result data=%04x\n", poll_result.rc_data);
200 242
243 if (ir->pwled) {
244 if (ir->pwledcnt >= PWLED_OFF) {
245 ir->pwled = 0;
246 ir->pwledcnt = 0;
247 tm6000_flash_led(dev, 1);
248 } else
249 ir->pwledcnt += 1;
250 }
251
201 if (ir->key) { 252 if (ir->key) {
202 rc_keydown(ir->rc, poll_result.rc_data, 0); 253 rc_keydown(ir->rc, poll_result.rc_data, 0);
203 ir->key = 0; 254 ir->key = 0;
255 ir->pwled = 1;
256 ir->pwledcnt = 0;
257 tm6000_flash_led(dev, 0);
204 } 258 }
205 return; 259 return;
206} 260}
@@ -234,19 +288,80 @@ int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
234{ 288{
235 struct tm6000_IR *ir = rc->priv; 289 struct tm6000_IR *ir = rc->priv;
236 290
291 if (!ir)
292 return 0;
293
294 if ((rc->rc_map.scan) && (rc_type == RC_TYPE_NEC))
295 ir->key_addr = ((rc->rc_map.scan[0].scancode >> 8) & 0xffff);
296
237 ir->get_key = default_polling_getkey; 297 ir->get_key = default_polling_getkey;
298 ir->rc_type = rc_type;
238 299
239 tm6000_ir_config(ir); 300 tm6000_ir_config(ir);
240 /* TODO */ 301 /* TODO */
241 return 0; 302 return 0;
242} 303}
243 304
305int tm6000_ir_int_start(struct tm6000_core *dev)
306{
307 struct tm6000_IR *ir = dev->ir;
308 int pipe, size;
309 int err = -ENOMEM;
310
311
312 if (!ir)
313 return -ENODEV;
314
315 ir->int_urb = usb_alloc_urb(0, GFP_KERNEL);
316
317 pipe = usb_rcvintpipe(dev->udev,
318 dev->int_in.endp->desc.bEndpointAddress
319 & USB_ENDPOINT_NUMBER_MASK);
320
321 size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe));
322 dprintk("IR max size: %d\n", size);
323
324 ir->int_urb->transfer_buffer = kzalloc(size, GFP_KERNEL);
325 if (ir->int_urb->transfer_buffer == NULL) {
326 usb_free_urb(ir->int_urb);
327 return err;
328 }
329 dprintk("int interval: %d\n", dev->int_in.endp->desc.bInterval);
330 usb_fill_int_urb(ir->int_urb, dev->udev, pipe,
331 ir->int_urb->transfer_buffer, size,
332 tm6000_ir_urb_received, dev,
333 dev->int_in.endp->desc.bInterval);
334 err = usb_submit_urb(ir->int_urb, GFP_KERNEL);
335 if (err) {
336 kfree(ir->int_urb->transfer_buffer);
337 usb_free_urb(ir->int_urb);
338 return err;
339 }
340 ir->urb_data = kzalloc(size, GFP_KERNEL);
341
342 return 0;
343}
344
345void tm6000_ir_int_stop(struct tm6000_core *dev)
346{
347 struct tm6000_IR *ir = dev->ir;
348
349 if (!ir)
350 return;
351
352 usb_kill_urb(ir->int_urb);
353 kfree(ir->int_urb->transfer_buffer);
354 usb_free_urb(ir->int_urb);
355 ir->int_urb = NULL;
356 kfree(ir->urb_data);
357 ir->urb_data = NULL;
358}
359
244int tm6000_ir_init(struct tm6000_core *dev) 360int tm6000_ir_init(struct tm6000_core *dev)
245{ 361{
246 struct tm6000_IR *ir; 362 struct tm6000_IR *ir;
247 struct rc_dev *rc; 363 struct rc_dev *rc;
248 int err = -ENOMEM; 364 int err = -ENOMEM;
249 int pipe, size;
250 365
251 if (!enable_ir) 366 if (!enable_ir)
252 return -ENODEV; 367 return -ENODEV;
@@ -276,6 +391,9 @@ int tm6000_ir_init(struct tm6000_core *dev)
276 rc->driver_type = RC_DRIVER_SCANCODE; 391 rc->driver_type = RC_DRIVER_SCANCODE;
277 392
278 ir->polling = 50; 393 ir->polling = 50;
394 ir->pwled = 0;
395 ir->pwledcnt = 0;
396
279 397
280 snprintf(ir->name, sizeof(ir->name), "tm5600/60x0 IR (%s)", 398 snprintf(ir->name, sizeof(ir->name), "tm5600/60x0 IR (%s)",
281 dev->name); 399 dev->name);
@@ -298,32 +416,10 @@ int tm6000_ir_init(struct tm6000_core *dev)
298 if (&dev->int_in) { 416 if (&dev->int_in) {
299 dprintk("IR over int\n"); 417 dprintk("IR over int\n");
300 418
301 ir->int_urb = usb_alloc_urb(0, GFP_KERNEL); 419 err = tm6000_ir_int_start(dev);
302
303 pipe = usb_rcvintpipe(dev->udev,
304 dev->int_in.endp->desc.bEndpointAddress
305 & USB_ENDPOINT_NUMBER_MASK);
306 420
307 size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe)); 421 if (err)
308 dprintk("IR max size: %d\n", size);
309
310 ir->int_urb->transfer_buffer = kzalloc(size, GFP_KERNEL);
311 if (ir->int_urb->transfer_buffer == NULL) {
312 usb_free_urb(ir->int_urb);
313 goto out;
314 }
315 dprintk("int interval: %d\n", dev->int_in.endp->desc.bInterval);
316 usb_fill_int_urb(ir->int_urb, dev->udev, pipe,
317 ir->int_urb->transfer_buffer, size,
318 tm6000_ir_urb_received, dev,
319 dev->int_in.endp->desc.bInterval);
320 err = usb_submit_urb(ir->int_urb, GFP_KERNEL);
321 if (err) {
322 kfree(ir->int_urb->transfer_buffer);
323 usb_free_urb(ir->int_urb);
324 goto out; 422 goto out;
325 }
326 ir->urb_data = kzalloc(size, GFP_KERNEL);
327 } 423 }
328 424
329 /* ir register */ 425 /* ir register */
@@ -352,12 +448,7 @@ int tm6000_ir_fini(struct tm6000_core *dev)
352 rc_unregister_device(ir->rc); 448 rc_unregister_device(ir->rc);
353 449
354 if (ir->int_urb) { 450 if (ir->int_urb) {
355 usb_kill_urb(ir->int_urb); 451 tm6000_ir_int_stop(dev);
356 kfree(ir->int_urb->transfer_buffer);
357 usb_free_urb(ir->int_urb);
358 ir->int_urb = NULL;
359 kfree(ir->urb_data);
360 ir->urb_data = NULL;
361 } 452 }
362 453
363 kfree(ir); 454 kfree(ir);
diff --git a/drivers/staging/tm6000/tm6000-video.c b/drivers/staging/tm6000/tm6000-video.c
index 0dae427a21ec..8fe017c3721f 100644
--- a/drivers/staging/tm6000/tm6000-video.c
+++ b/drivers/staging/tm6000/tm6000-video.c
@@ -545,11 +545,16 @@ static int tm6000_prepare_isoc(struct tm6000_core *dev, unsigned int framesize)
545 545
546 /* De-allocates all pending stuff */ 546 /* De-allocates all pending stuff */
547 tm6000_uninit_isoc(dev); 547 tm6000_uninit_isoc(dev);
548 /* Stop interrupt USB pipe */
549 tm6000_ir_int_stop(dev);
548 550
549 usb_set_interface(dev->udev, 551 usb_set_interface(dev->udev,
550 dev->isoc_in.bInterfaceNumber, 552 dev->isoc_in.bInterfaceNumber,
551 dev->isoc_in.bAlternateSetting); 553 dev->isoc_in.bAlternateSetting);
552 554
555 /* Start interrupt USB pipe */
556 tm6000_ir_int_start(dev);
557
553 pipe = usb_rcvisocpipe(dev->udev, 558 pipe = usb_rcvisocpipe(dev->udev,
554 dev->isoc_in.endp->desc.bEndpointAddress & 559 dev->isoc_in.endp->desc.bEndpointAddress &
555 USB_ENDPOINT_NUMBER_MASK); 560 USB_ENDPOINT_NUMBER_MASK);
diff --git a/drivers/staging/tm6000/tm6000.h b/drivers/staging/tm6000/tm6000.h
index 46017b603190..bf11eeec92c7 100644
--- a/drivers/staging/tm6000/tm6000.h
+++ b/drivers/staging/tm6000/tm6000.h
@@ -266,6 +266,7 @@ struct tm6000_fh {
266int tm6000_tuner_callback(void *ptr, int component, int command, int arg); 266int tm6000_tuner_callback(void *ptr, int component, int command, int arg);
267int tm6000_xc5000_callback(void *ptr, int component, int command, int arg); 267int tm6000_xc5000_callback(void *ptr, int component, int command, int arg);
268int tm6000_cards_setup(struct tm6000_core *dev); 268int tm6000_cards_setup(struct tm6000_core *dev);
269void tm6000_flash_led(struct tm6000_core *dev, u8 state);
269 270
270/* In tm6000-core.c */ 271/* In tm6000-core.c */
271 272
@@ -332,6 +333,8 @@ int tm6000_queue_init(struct tm6000_core *dev);
332int tm6000_ir_init(struct tm6000_core *dev); 333int tm6000_ir_init(struct tm6000_core *dev);
333int tm6000_ir_fini(struct tm6000_core *dev); 334int tm6000_ir_fini(struct tm6000_core *dev);
334void tm6000_ir_wait(struct tm6000_core *dev, u8 state); 335void tm6000_ir_wait(struct tm6000_core *dev, u8 state);
336int tm6000_ir_int_start(struct tm6000_core *dev);
337void tm6000_ir_int_stop(struct tm6000_core *dev);
335 338
336/* Debug stuff */ 339/* Debug stuff */
337 340