diff options
Diffstat (limited to 'drivers/media/video/tm6000/tm6000-input.c')
-rw-r--r-- | drivers/media/video/tm6000/tm6000-input.c | 407 |
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 | ||
32 | static unsigned int ir_debug; | 32 | static unsigned int ir_debug; |
33 | module_param(ir_debug, int, 0644); | 33 | module_param(ir_debug, int, 0644); |
34 | MODULE_PARM_DESC(ir_debug, "enable debug message [IR]"); | 34 | MODULE_PARM_DESC(ir_debug, "debug message level"); |
35 | 35 | ||
36 | static unsigned int enable_ir = 1; | 36 | static unsigned int enable_ir = 1; |
37 | module_param(enable_ir, int, 0644); | 37 | module_param(enable_ir, int, 0644); |
38 | MODULE_PARM_DESC(enable_ir, "enable ir (default is enable)"); | 38 | MODULE_PARM_DESC(enable_ir, "enable ir (default is enable)"); |
39 | 39 | ||
40 | /* number of 50ms for ON-OFF-ON power led */ | 40 | static unsigned int ir_clock_mhz = 12; |
41 | /* show IR activity */ | 41 | module_param(ir_clock_mhz, int, 0644); |
42 | #define PWLED_OFF 2 | 42 | MODULE_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 | ||
51 | struct tm6000_ir_poll_result { | 54 | struct 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 | |||
79 | void tm6000_ir_wait(struct tm6000_core *dev, u8 state) | 77 | void 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 | |||
93 | static int tm6000_ir_config(struct tm6000_IR *ir) | 92 | static 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 | ||
165 | static int default_polling_getkey(struct tm6000_IR *ir, | 204 | static 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 | ||
228 | static void tm6000_ir_handle_key(struct tm6000_IR *ir) | 246 | static 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 | |||
262 | static 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 | ||
270 | static int tm6000_ir_start(struct rc_dev *rc) | 281 | static 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 | ||
305 | int tm6000_ir_int_start(struct tm6000_core *dev) | 320 | static 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 | ||
347 | void tm6000_ir_int_stop(struct tm6000_core *dev) | 361 | static 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 | |
376 | int 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 | |||
386 | void 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 | ||
362 | int tm6000_ir_init(struct tm6000_core *dev) | 396 | int 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; |