aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/radio/radio-isa.c
diff options
context:
space:
mode:
authorOndrej Zary <linux@rainbow-software.org>2012-03-22 13:53:01 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-04-10 18:52:16 -0400
commit865d7ec93433a3c9d8d2c2372e582853f52a7327 (patch)
treed4f89b62ded8ea7c06492addf5a0dfbd45f3e54a /drivers/media/radio/radio-isa.c
parent8766e86535c9c9d46621f285b85266b2975348c2 (diff)
[media] radio-isa: PnP support for the new ISA radio framework
Add PnP support to the new ISA radio framework. Signed-off-by: Ondrej Zary <linux@rainbow-software.org> Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/radio/radio-isa.c')
-rw-r--r--drivers/media/radio/radio-isa.c155
1 files changed, 108 insertions, 47 deletions
diff --git a/drivers/media/radio/radio-isa.c b/drivers/media/radio/radio-isa.c
index 06f906351fad..ed9039f8571c 100644
--- a/drivers/media/radio/radio-isa.c
+++ b/drivers/media/radio/radio-isa.c
@@ -199,56 +199,31 @@ static bool radio_isa_valid_io(const struct radio_isa_driver *drv, int io)
199 return false; 199 return false;
200} 200}
201 201
202int radio_isa_probe(struct device *pdev, unsigned int dev) 202struct radio_isa_card *radio_isa_alloc(struct radio_isa_driver *drv,
203 struct device *pdev)
203{ 204{
204 struct radio_isa_driver *drv = pdev->platform_data;
205 const struct radio_isa_ops *ops = drv->ops;
206 struct v4l2_device *v4l2_dev; 205 struct v4l2_device *v4l2_dev;
207 struct radio_isa_card *isa; 206 struct radio_isa_card *isa = drv->ops->alloc();
208 int res; 207 if (!isa)
208 return NULL;
209 209
210 isa = drv->ops->alloc();
211 if (isa == NULL)
212 return -ENOMEM;
213 dev_set_drvdata(pdev, isa); 210 dev_set_drvdata(pdev, isa);
214 isa->drv = drv; 211 isa->drv = drv;
215 isa->io = drv->io_params[dev];
216 v4l2_dev = &isa->v4l2_dev; 212 v4l2_dev = &isa->v4l2_dev;
217 strlcpy(v4l2_dev->name, dev_name(pdev), sizeof(v4l2_dev->name)); 213 strlcpy(v4l2_dev->name, dev_name(pdev), sizeof(v4l2_dev->name));
218 214
219 if (drv->probe && ops->probe) { 215 return isa;
220 int i; 216}
221
222 for (i = 0; i < drv->num_of_io_ports; ++i) {
223 int io = drv->io_ports[i];
224
225 if (request_region(io, drv->region_size, v4l2_dev->name)) {
226 bool found = ops->probe(isa, io);
227
228 release_region(io, drv->region_size);
229 if (found) {
230 isa->io = io;
231 break;
232 }
233 }
234 }
235 }
236
237 if (!radio_isa_valid_io(drv, isa->io)) {
238 int i;
239 217
240 if (isa->io < 0) 218int radio_isa_common_probe(struct radio_isa_card *isa, struct device *pdev,
241 return -ENODEV; 219 int radio_nr, unsigned region_size)
242 v4l2_err(v4l2_dev, "you must set an I/O address with io=0x%03x", 220{
243 drv->io_ports[0]); 221 const struct radio_isa_driver *drv = isa->drv;
244 for (i = 1; i < drv->num_of_io_ports; i++) 222 const struct radio_isa_ops *ops = drv->ops;
245 printk(KERN_CONT "/0x%03x", drv->io_ports[i]); 223 struct v4l2_device *v4l2_dev = &isa->v4l2_dev;
246 printk(KERN_CONT ".\n"); 224 int res;
247 kfree(isa);
248 return -EINVAL;
249 }
250 225
251 if (!request_region(isa->io, drv->region_size, v4l2_dev->name)) { 226 if (!request_region(isa->io, region_size, v4l2_dev->name)) {
252 v4l2_err(v4l2_dev, "port 0x%x already in use\n", isa->io); 227 v4l2_err(v4l2_dev, "port 0x%x already in use\n", isa->io);
253 kfree(isa); 228 kfree(isa);
254 return -EBUSY; 229 return -EBUSY;
@@ -301,8 +276,8 @@ int radio_isa_probe(struct device *pdev, unsigned int dev)
301 v4l2_err(v4l2_dev, "Could not setup card\n"); 276 v4l2_err(v4l2_dev, "Could not setup card\n");
302 goto err_node_reg; 277 goto err_node_reg;
303 } 278 }
304 res = video_register_device(&isa->vdev, VFL_TYPE_RADIO, 279 res = video_register_device(&isa->vdev, VFL_TYPE_RADIO, radio_nr);
305 drv->radio_nr_params[dev]); 280
306 if (res < 0) { 281 if (res < 0) {
307 v4l2_err(v4l2_dev, "Could not register device node\n"); 282 v4l2_err(v4l2_dev, "Could not register device node\n");
308 goto err_node_reg; 283 goto err_node_reg;
@@ -317,24 +292,110 @@ err_node_reg:
317err_hdl: 292err_hdl:
318 v4l2_device_unregister(&isa->v4l2_dev); 293 v4l2_device_unregister(&isa->v4l2_dev);
319err_dev_reg: 294err_dev_reg:
320 release_region(isa->io, drv->region_size); 295 release_region(isa->io, region_size);
321 kfree(isa); 296 kfree(isa);
322 return res; 297 return res;
323} 298}
324EXPORT_SYMBOL_GPL(radio_isa_probe);
325 299
326int radio_isa_remove(struct device *pdev, unsigned int dev) 300int radio_isa_common_remove(struct radio_isa_card *isa, unsigned region_size)
327{ 301{
328 struct radio_isa_card *isa = dev_get_drvdata(pdev);
329 const struct radio_isa_ops *ops = isa->drv->ops; 302 const struct radio_isa_ops *ops = isa->drv->ops;
330 303
331 ops->s_mute_volume(isa, true, isa->volume ? isa->volume->cur.val : 0); 304 ops->s_mute_volume(isa, true, isa->volume ? isa->volume->cur.val : 0);
332 video_unregister_device(&isa->vdev); 305 video_unregister_device(&isa->vdev);
333 v4l2_ctrl_handler_free(&isa->hdl); 306 v4l2_ctrl_handler_free(&isa->hdl);
334 v4l2_device_unregister(&isa->v4l2_dev); 307 v4l2_device_unregister(&isa->v4l2_dev);
335 release_region(isa->io, isa->drv->region_size); 308 release_region(isa->io, region_size);
336 v4l2_info(&isa->v4l2_dev, "Removed radio card %s\n", isa->drv->card); 309 v4l2_info(&isa->v4l2_dev, "Removed radio card %s\n", isa->drv->card);
337 kfree(isa); 310 kfree(isa);
338 return 0; 311 return 0;
339} 312}
313
314int radio_isa_probe(struct device *pdev, unsigned int dev)
315{
316 struct radio_isa_driver *drv = pdev->platform_data;
317 const struct radio_isa_ops *ops = drv->ops;
318 struct v4l2_device *v4l2_dev;
319 struct radio_isa_card *isa;
320
321 isa = radio_isa_alloc(drv, pdev);
322 if (!isa)
323 return -ENOMEM;
324 isa->io = drv->io_params[dev];
325 v4l2_dev = &isa->v4l2_dev;
326
327 if (drv->probe && ops->probe) {
328 int i;
329
330 for (i = 0; i < drv->num_of_io_ports; ++i) {
331 int io = drv->io_ports[i];
332
333 if (request_region(io, drv->region_size, v4l2_dev->name)) {
334 bool found = ops->probe(isa, io);
335
336 release_region(io, drv->region_size);
337 if (found) {
338 isa->io = io;
339 break;
340 }
341 }
342 }
343 }
344
345 if (!radio_isa_valid_io(drv, isa->io)) {
346 int i;
347
348 if (isa->io < 0)
349 return -ENODEV;
350 v4l2_err(v4l2_dev, "you must set an I/O address with io=0x%03x",
351 drv->io_ports[0]);
352 for (i = 1; i < drv->num_of_io_ports; i++)
353 printk(KERN_CONT "/0x%03x", drv->io_ports[i]);
354 printk(KERN_CONT ".\n");
355 kfree(isa);
356 return -EINVAL;
357 }
358
359 return radio_isa_common_probe(isa, pdev, drv->radio_nr_params[dev],
360 drv->region_size);
361}
362EXPORT_SYMBOL_GPL(radio_isa_probe);
363
364int radio_isa_remove(struct device *pdev, unsigned int dev)
365{
366 struct radio_isa_card *isa = dev_get_drvdata(pdev);
367
368 return radio_isa_common_remove(isa, isa->drv->region_size);
369}
340EXPORT_SYMBOL_GPL(radio_isa_remove); 370EXPORT_SYMBOL_GPL(radio_isa_remove);
371
372#ifdef CONFIG_PNP
373int radio_isa_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
374{
375 struct pnp_driver *pnp_drv = to_pnp_driver(dev->dev.driver);
376 struct radio_isa_driver *drv = container_of(pnp_drv,
377 struct radio_isa_driver, pnp_driver);
378 struct radio_isa_card *isa;
379
380 if (!pnp_port_valid(dev, 0))
381 return -ENODEV;
382
383 isa = radio_isa_alloc(drv, &dev->dev);
384 if (!isa)
385 return -ENOMEM;
386
387 isa->io = pnp_port_start(dev, 0);
388
389 return radio_isa_common_probe(isa, &dev->dev, drv->radio_nr_params[0],
390 pnp_port_len(dev, 0));
391}
392EXPORT_SYMBOL_GPL(radio_isa_pnp_probe);
393
394void radio_isa_pnp_remove(struct pnp_dev *dev)
395{
396 struct radio_isa_card *isa = dev_get_drvdata(&dev->dev);
397
398 radio_isa_common_remove(isa, pnp_port_len(dev, 0));
399}
400EXPORT_SYMBOL_GPL(radio_isa_pnp_remove);
401#endif