diff options
author | Dmitry Torokhov <dtor@insightbb.com> | 2006-11-20 08:23:04 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-12-10 06:04:52 -0500 |
commit | b07b4783fb30dee8c542fc76ed8993108d46d6aa (patch) | |
tree | 0e57cc5887511b31e964299820a7adf37e6e45ae /drivers/media/video/cx88/cx88-input.c | |
parent | ff67c614e23bf5a3c16968e2c42ab442121c4beb (diff) |
V4L/DVB (4854): Handle errors from input_register_device()
Also sprinkled some input_sync() throughout the code.
Acked-by: Ricardo Cerqueira <v4l@cerqueira.org>
Acked-by: Oliver Endriss <o.endriss@gmx.de>
Acked-by: Andrew de Quincey <adq_dvb@lidskialf.net>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/cx88/cx88-input.c')
-rw-r--r-- | drivers/media/video/cx88/cx88-input.c | 77 |
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..c6d412b1f218 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 | ||
158 | static 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, ir); | ||
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 | |||
174 | static 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 | ||
160 | int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | 189 | int 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 | ||
329 | int cx88_ir_fini(struct cx88_core *core) | 354 | int 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 | ||