aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx88/cx88-input.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/cx88/cx88-input.c')
-rw-r--r--drivers/media/video/cx88/cx88-input.c77
1 files changed, 47 insertions, 30 deletions
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index e60a0a52e4b2..8136673fe9e8 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -155,6 +155,35 @@ static void cx88_ir_work(struct work_struct *work)
155 mod_timer(&ir->timer, timeout); 155 mod_timer(&ir->timer, timeout);
156} 156}
157 157
158static void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir)
159{
160 if (ir->polling) {
161 INIT_WORK(&ir->work, cx88_ir_work);
162 init_timer(&ir->timer);
163 ir->timer.function = ir_timer;
164 ir->timer.data = (unsigned long)ir;
165 schedule_work(&ir->work);
166 }
167 if (ir->sampling) {
168 core->pci_irqmask |= (1 << 18); /* IR_SMP_INT */
169 cx_write(MO_DDS_IO, 0xa80a80); /* 4 kHz sample rate */
170 cx_write(MO_DDSCFG_IO, 0x5); /* enable */
171 }
172}
173
174static void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir)
175{
176 if (ir->sampling) {
177 cx_write(MO_DDSCFG_IO, 0x0);
178 core->pci_irqmask &= ~(1 << 18);
179 }
180
181 if (ir->polling) {
182 del_timer_sync(&ir->timer);
183 flush_scheduled_work();
184 }
185}
186
158/* ---------------------------------------------------------------------- */ 187/* ---------------------------------------------------------------------- */
159 188
160int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) 189int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
@@ -163,14 +192,12 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
163 struct input_dev *input_dev; 192 struct input_dev *input_dev;
164 IR_KEYTAB_TYPE *ir_codes = NULL; 193 IR_KEYTAB_TYPE *ir_codes = NULL;
165 int ir_type = IR_TYPE_OTHER; 194 int ir_type = IR_TYPE_OTHER;
195 int err = -ENOMEM;
166 196
167 ir = kzalloc(sizeof(*ir), GFP_KERNEL); 197 ir = kzalloc(sizeof(*ir), GFP_KERNEL);
168 input_dev = input_allocate_device(); 198 input_dev = input_allocate_device();
169 if (!ir || !input_dev) { 199 if (!ir || !input_dev)
170 kfree(ir); 200 goto err_out_free;
171 input_free_device(input_dev);
172 return -ENOMEM;
173 }
174 201
175 ir->input = input_dev; 202 ir->input = input_dev;
176 203
@@ -280,9 +307,8 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
280 } 307 }
281 308
282 if (NULL == ir_codes) { 309 if (NULL == ir_codes) {
283 kfree(ir); 310 err = -ENODEV;
284 input_free_device(input_dev); 311 goto err_out_free;
285 return -ENODEV;
286 } 312 }
287 313
288 /* init input device */ 314 /* init input device */
@@ -307,23 +333,22 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
307 ir->core = core; 333 ir->core = core;
308 core->ir = ir; 334 core->ir = ir;
309 335
310 if (ir->polling) { 336 cx88_ir_start(core, ir);
311 INIT_WORK(&ir->work, cx88_ir_work);
312 init_timer(&ir->timer);
313 ir->timer.function = ir_timer;
314 ir->timer.data = (unsigned long)ir;
315 schedule_work(&ir->work);
316 }
317 if (ir->sampling) {
318 core->pci_irqmask |= (1 << 18); /* IR_SMP_INT */
319 cx_write(MO_DDS_IO, 0xa80a80); /* 4 kHz sample rate */
320 cx_write(MO_DDSCFG_IO, 0x5); /* enable */
321 }
322 337
323 /* all done */ 338 /* all done */
324 input_register_device(ir->input); 339 err = input_register_device(ir->input);
340 if (err)
341 goto err_out_stop;
325 342
326 return 0; 343 return 0;
344
345 err_out_stop:
346 cx88_ir_stop(core, ir);
347 core->ir = NULL;
348 err_out_free:
349 input_free_device(input_dev);
350 kfree(ir);
351 return err;
327} 352}
328 353
329int cx88_ir_fini(struct cx88_core *core) 354int cx88_ir_fini(struct cx88_core *core)
@@ -334,15 +359,7 @@ int cx88_ir_fini(struct cx88_core *core)
334 if (NULL == ir) 359 if (NULL == ir)
335 return 0; 360 return 0;
336 361
337 if (ir->sampling) { 362 cx88_ir_stop(core, ir);
338 cx_write(MO_DDSCFG_IO, 0x0);
339 core->pci_irqmask &= ~(1 << 18);
340 }
341 if (ir->polling) {
342 del_timer(&ir->timer);
343 flush_scheduled_work();
344 }
345
346 input_unregister_device(ir->input); 363 input_unregister_device(ir->input);
347 kfree(ir); 364 kfree(ir);
348 365