diff options
author | Jonathan Corbet <corbet@lwn.net> | 2010-04-22 19:39:34 -0400 |
---|---|---|
committer | Jonathan Corbet <corbet@lwn.net> | 2010-05-07 19:17:37 -0400 |
commit | 7582eb9be85f35271fd2569681a88a5b243e9380 (patch) | |
tree | 84a234364b9e314e7b25800d473e6047da379a56 /drivers/video/via/via-core.c | |
parent | 75b035ace904761b8a340b524533a36e37313b29 (diff) |
viafb: Turn GPIO and i2c into proper platform devices
Another step toward making this thing a real multifunction device driver.
Cc: ScottFang@viatech.com.cn
Cc: JosephChan@via.com.tw
Cc: Harald Welte <laforge@gnumonks.org>
Acked-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
Diffstat (limited to 'drivers/video/via/via-core.c')
-rw-r--r-- | drivers/video/via/via-core.c | 91 |
1 files changed, 75 insertions, 16 deletions
diff --git a/drivers/video/via/via-core.c b/drivers/video/via/via-core.c index a1b5dae285a4..5a78ef9cb382 100644 --- a/drivers/video/via/via-core.c +++ b/drivers/video/via/via-core.c | |||
@@ -190,6 +190,70 @@ static void __devexit via_pci_teardown_mmio(struct viafb_dev *vdev) | |||
190 | iounmap(vdev->engine_mmio); | 190 | iounmap(vdev->engine_mmio); |
191 | } | 191 | } |
192 | 192 | ||
193 | /* | ||
194 | * Create our subsidiary devices. | ||
195 | */ | ||
196 | static struct viafb_subdev_info { | ||
197 | char *name; | ||
198 | struct platform_device *platdev; | ||
199 | } viafb_subdevs[] = { | ||
200 | { | ||
201 | .name = "viafb-gpio", | ||
202 | }, | ||
203 | { | ||
204 | .name = "viafb-i2c", | ||
205 | } | ||
206 | }; | ||
207 | #define N_SUBDEVS ARRAY_SIZE(viafb_subdevs) | ||
208 | |||
209 | static int __devinit via_create_subdev(struct viafb_dev *vdev, | ||
210 | struct viafb_subdev_info *info) | ||
211 | { | ||
212 | int ret; | ||
213 | |||
214 | info->platdev = platform_device_alloc(info->name, -1); | ||
215 | if (!info->platdev) { | ||
216 | dev_err(&vdev->pdev->dev, "Unable to allocate pdev %s\n", | ||
217 | info->name); | ||
218 | return -ENOMEM; | ||
219 | } | ||
220 | info->platdev->dev.parent = &vdev->pdev->dev; | ||
221 | info->platdev->dev.platform_data = vdev; | ||
222 | ret = platform_device_add(info->platdev); | ||
223 | if (ret) { | ||
224 | dev_err(&vdev->pdev->dev, "Unable to add pdev %s\n", | ||
225 | info->name); | ||
226 | platform_device_put(info->platdev); | ||
227 | info->platdev = NULL; | ||
228 | } | ||
229 | return ret; | ||
230 | } | ||
231 | |||
232 | static int __devinit via_setup_subdevs(struct viafb_dev *vdev) | ||
233 | { | ||
234 | int i; | ||
235 | |||
236 | /* | ||
237 | * Ignore return values. Even if some of the devices | ||
238 | * fail to be created, we'll still be able to use some | ||
239 | * of the rest. | ||
240 | */ | ||
241 | for (i = 0; i < N_SUBDEVS; i++) | ||
242 | via_create_subdev(vdev, viafb_subdevs + i); | ||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | static void __devexit via_teardown_subdevs(void) | ||
247 | { | ||
248 | int i; | ||
249 | |||
250 | for (i = 0; i < N_SUBDEVS; i++) | ||
251 | if (viafb_subdevs[i].platdev) { | ||
252 | viafb_subdevs[i].platdev->dev.platform_data = NULL; | ||
253 | platform_device_unregister(viafb_subdevs[i].platdev); | ||
254 | } | ||
255 | } | ||
256 | |||
193 | 257 | ||
194 | static int __devinit via_pci_probe(struct pci_dev *pdev, | 258 | static int __devinit via_pci_probe(struct pci_dev *pdev, |
195 | const struct pci_device_id *ent) | 259 | const struct pci_device_id *ent) |
@@ -205,33 +269,25 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, | |||
205 | memset(&global_dev, 0, sizeof(global_dev)); | 269 | memset(&global_dev, 0, sizeof(global_dev)); |
206 | global_dev.pdev = pdev; | 270 | global_dev.pdev = pdev; |
207 | global_dev.chip_type = ent->driver_data; | 271 | global_dev.chip_type = ent->driver_data; |
272 | global_dev.port_cfg = adap_configs; | ||
208 | spin_lock_init(&global_dev.reg_lock); | 273 | spin_lock_init(&global_dev.reg_lock); |
209 | ret = via_pci_setup_mmio(&global_dev); | 274 | ret = via_pci_setup_mmio(&global_dev); |
210 | if (ret) | 275 | if (ret) |
211 | goto out_disable; | 276 | goto out_disable; |
212 | /* | 277 | /* |
213 | * Create the I2C busses. Bailing out on failure seems extreme, | 278 | * Create our subdevices. Continue even if some things fail. |
214 | * but that's what the code did before. | ||
215 | */ | 279 | */ |
216 | ret = viafb_create_i2c_busses(&global_dev, adap_configs); | 280 | via_setup_subdevs(&global_dev); |
217 | if (ret) | ||
218 | goto out_teardown; | ||
219 | /* | 281 | /* |
220 | * Set up the framebuffer. | 282 | * Set up the framebuffer. |
221 | */ | 283 | */ |
222 | ret = via_fb_pci_probe(&global_dev); | 284 | ret = via_fb_pci_probe(&global_dev); |
223 | if (ret) | 285 | if (ret) |
224 | goto out_i2c; | 286 | goto out_subdevs; |
225 | /* | ||
226 | * Create the GPIOs. We continue whether or not this succeeds; | ||
227 | * the framebuffer might be useful even without GPIO ports. | ||
228 | */ | ||
229 | ret = viafb_create_gpios(&global_dev, adap_configs); | ||
230 | return 0; | 287 | return 0; |
231 | 288 | ||
232 | out_i2c: | 289 | out_subdevs: |
233 | viafb_delete_i2c_busses(); | 290 | via_teardown_subdevs(); |
234 | out_teardown: | ||
235 | via_pci_teardown_mmio(&global_dev); | 291 | via_pci_teardown_mmio(&global_dev); |
236 | out_disable: | 292 | out_disable: |
237 | pci_disable_device(pdev); | 293 | pci_disable_device(pdev); |
@@ -240,8 +296,7 @@ out_disable: | |||
240 | 296 | ||
241 | static void __devexit via_pci_remove(struct pci_dev *pdev) | 297 | static void __devexit via_pci_remove(struct pci_dev *pdev) |
242 | { | 298 | { |
243 | viafb_destroy_gpios(); | 299 | via_teardown_subdevs(); |
244 | viafb_delete_i2c_busses(); | ||
245 | via_fb_pci_remove(pdev); | 300 | via_fb_pci_remove(pdev); |
246 | via_pci_teardown_mmio(&global_dev); | 301 | via_pci_teardown_mmio(&global_dev); |
247 | pci_disable_device(pdev); | 302 | pci_disable_device(pdev); |
@@ -289,12 +344,16 @@ static int __init via_core_init(void) | |||
289 | ret = viafb_init(); | 344 | ret = viafb_init(); |
290 | if (ret) | 345 | if (ret) |
291 | return ret; | 346 | return ret; |
347 | viafb_i2c_init(); | ||
348 | viafb_gpio_init(); | ||
292 | return pci_register_driver(&via_driver); | 349 | return pci_register_driver(&via_driver); |
293 | } | 350 | } |
294 | 351 | ||
295 | static void __exit via_core_exit(void) | 352 | static void __exit via_core_exit(void) |
296 | { | 353 | { |
297 | pci_unregister_driver(&via_driver); | 354 | pci_unregister_driver(&via_driver); |
355 | viafb_gpio_exit(); | ||
356 | viafb_i2c_exit(); | ||
298 | viafb_exit(); | 357 | viafb_exit(); |
299 | } | 358 | } |
300 | 359 | ||