aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorJonathan Corbet <corbet@lwn.net>2010-04-22 19:39:34 -0400
committerJonathan Corbet <corbet@lwn.net>2010-05-07 19:17:37 -0400
commit7582eb9be85f35271fd2569681a88a5b243e9380 (patch)
tree84a234364b9e314e7b25800d473e6047da379a56 /drivers/video
parent75b035ace904761b8a340b524533a36e37313b29 (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')
-rw-r--r--drivers/video/via/via-core.c91
-rw-r--r--drivers/video/via/via-core.h1
-rw-r--r--drivers/video/via/via-gpio.c49
-rw-r--r--drivers/video/via/via-gpio.h5
-rw-r--r--drivers/video/via/via_i2c.c29
-rw-r--r--drivers/video/via/via_i2c.h6
6 files changed, 140 insertions, 41 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 */
196static 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
209static 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
232static 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
246static 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
194static int __devinit via_pci_probe(struct pci_dev *pdev, 258static 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
232out_i2c: 289out_subdevs:
233 viafb_delete_i2c_busses(); 290 via_teardown_subdevs();
234out_teardown:
235 via_pci_teardown_mmio(&global_dev); 291 via_pci_teardown_mmio(&global_dev);
236out_disable: 292out_disable:
237 pci_disable_device(pdev); 293 pci_disable_device(pdev);
@@ -240,8 +296,7 @@ out_disable:
240 296
241static void __devexit via_pci_remove(struct pci_dev *pdev) 297static 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
295static void __exit via_core_exit(void) 352static 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
diff --git a/drivers/video/via/via-core.h b/drivers/video/via/via-core.h
index d004290dc8f1..ac89c2aa98b5 100644
--- a/drivers/video/via/via-core.h
+++ b/drivers/video/via/via-core.h
@@ -63,6 +63,7 @@ struct via_port_cfg {
63struct viafb_dev { 63struct viafb_dev {
64 struct pci_dev *pdev; 64 struct pci_dev *pdev;
65 int chip_type; 65 int chip_type;
66 struct via_port_cfg *port_cfg;
66 /* 67 /*
67 * Spinlock for access to device registers. Not yet 68 * Spinlock for access to device registers. Not yet
68 * globally used. 69 * globally used.
diff --git a/drivers/video/via/via-gpio.c b/drivers/video/via/via-gpio.c
index 6b361177bf03..44537be1f070 100644
--- a/drivers/video/via/via-gpio.c
+++ b/drivers/video/via/via-gpio.c
@@ -7,6 +7,7 @@
7 7
8#include <linux/spinlock.h> 8#include <linux/spinlock.h>
9#include <linux/gpio.h> 9#include <linux/gpio.h>
10#include <linux/platform_device.h>
10#include "via-core.h" 11#include "via-core.h"
11#include "via-gpio.h" 12#include "via-gpio.h"
12#include "global.h" 13#include "global.h"
@@ -172,12 +173,27 @@ static void viafb_gpio_disable(struct viafb_gpio *gpio)
172 via_write_reg_mask(VIASR, gpio->vg_port_index, 0, 0x02); 173 via_write_reg_mask(VIASR, gpio->vg_port_index, 0, 0x02);
173} 174}
174 175
176/*
177 * Look up a specific gpio and return the number it was assigned.
178 */
179int viafb_gpio_lookup(const char *name)
180{
181 int i;
175 182
183 for (i = 0; i < gpio_config.gpio_chip.ngpio; i++)
184 if (!strcmp(name, gpio_config.active_gpios[i]->vg_name))
185 return gpio_config.gpio_chip.base + i;
186 return -1;
187}
188EXPORT_SYMBOL_GPL(viafb_gpio_lookup);
176 189
177 190/*
178int viafb_create_gpios(struct viafb_dev *vdev, 191 * Platform device stuff.
179 const struct via_port_cfg *port_cfg) 192 */
193static __devinit int viafb_gpio_probe(struct platform_device *platdev)
180{ 194{
195 struct viafb_dev *vdev = platdev->dev.platform_data;
196 struct via_port_cfg *port_cfg = vdev->port_cfg;
181 int i, ngpio = 0, ret; 197 int i, ngpio = 0, ret;
182 struct viafb_gpio *gpio; 198 struct viafb_gpio *gpio;
183 unsigned long flags; 199 unsigned long flags;
@@ -222,11 +238,10 @@ int viafb_create_gpios(struct viafb_dev *vdev,
222 gpio_config.gpio_chip.ngpio = 0; 238 gpio_config.gpio_chip.ngpio = 0;
223 } 239 }
224 return ret; 240 return ret;
225/* Port enable ? */
226} 241}
227 242
228 243
229int viafb_destroy_gpios(void) 244static int viafb_gpio_remove(struct platform_device *platdev)
230{ 245{
231 unsigned long flags; 246 unsigned long flags;
232 int ret = 0, i; 247 int ret = 0, i;
@@ -253,16 +268,20 @@ out:
253 return ret; 268 return ret;
254} 269}
255 270
256/* 271static struct platform_driver via_gpio_driver = {
257 * Look up a specific gpio and return the number it was assigned. 272 .driver = {
258 */ 273 .name = "viafb-gpio",
259int viafb_gpio_lookup(const char *name) 274 },
275 .probe = viafb_gpio_probe,
276 .remove = viafb_gpio_remove,
277};
278
279int viafb_gpio_init(void)
260{ 280{
261 int i; 281 return platform_driver_register(&via_gpio_driver);
282}
262 283
263 for (i = 0; i < gpio_config.gpio_chip.ngpio; i++) 284void viafb_gpio_exit(void)
264 if (!strcmp(name, gpio_config.active_gpios[i]->vg_name)) 285{
265 return gpio_config.gpio_chip.base + i; 286 platform_driver_unregister(&via_gpio_driver);
266 return -1;
267} 287}
268EXPORT_SYMBOL_GPL(viafb_gpio_lookup);
diff --git a/drivers/video/via/via-gpio.h b/drivers/video/via/via-gpio.h
index 7b53f966eb4b..8281aea3dd6d 100644
--- a/drivers/video/via/via-gpio.h
+++ b/drivers/video/via/via-gpio.h
@@ -8,8 +8,7 @@
8#ifndef __VIA_GPIO_H__ 8#ifndef __VIA_GPIO_H__
9#define __VIA_GPIO_H__ 9#define __VIA_GPIO_H__
10 10
11extern int viafb_create_gpios(struct viafb_dev *vdev,
12 const struct via_port_cfg *port_cfg);
13extern int viafb_destroy_gpios(void);
14extern int viafb_gpio_lookup(const char *name); 11extern int viafb_gpio_lookup(const char *name);
12extern int viafb_gpio_init(void);
13extern void viafb_gpio_exit(void);
15#endif 14#endif
diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c
index 116fd3e62934..3ff60b280d88 100644
--- a/drivers/video/via/via_i2c.c
+++ b/drivers/video/via/via_i2c.c
@@ -19,6 +19,7 @@
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */ 20 */
21 21
22#include <linux/platform_device.h>
22#include "via-core.h" 23#include "via-core.h"
23#include "via_i2c.h" 24#include "via_i2c.h"
24#include "global.h" 25#include "global.h"
@@ -185,11 +186,14 @@ static int create_i2c_bus(struct i2c_adapter *adapter,
185 return i2c_bit_add_bus(adapter); 186 return i2c_bit_add_bus(adapter);
186} 187}
187 188
188int viafb_create_i2c_busses(struct viafb_dev *dev, struct via_port_cfg *configs) 189static int viafb_i2c_probe(struct platform_device *platdev)
189{ 190{
190 int i, ret; 191 int i, ret;
192 struct via_port_cfg *configs;
193
194 i2c_vdev = platdev->dev.platform_data;
195 configs = i2c_vdev->port_cfg;
191 196
192 i2c_vdev = dev;
193 for (i = 0; i < VIAFB_NUM_PORTS; i++) { 197 for (i = 0; i < VIAFB_NUM_PORTS; i++) {
194 struct via_port_cfg *adap_cfg = configs++; 198 struct via_port_cfg *adap_cfg = configs++;
195 struct via_i2c_stuff *i2c_stuff = &via_i2c_par[i]; 199 struct via_i2c_stuff *i2c_stuff = &via_i2c_par[i];
@@ -211,7 +215,7 @@ int viafb_create_i2c_busses(struct viafb_dev *dev, struct via_port_cfg *configs)
211 return 0; 215 return 0;
212} 216}
213 217
214void viafb_delete_i2c_busses(void) 218static int viafb_i2c_remove(struct platform_device *platdev)
215{ 219{
216 int i; 220 int i;
217 221
@@ -224,4 +228,23 @@ void viafb_delete_i2c_busses(void)
224 if (i2c_stuff->adapter.algo_data == &i2c_stuff->algo) 228 if (i2c_stuff->adapter.algo_data == &i2c_stuff->algo)
225 i2c_del_adapter(&i2c_stuff->adapter); 229 i2c_del_adapter(&i2c_stuff->adapter);
226 } 230 }
231 return 0;
232}
233
234static struct platform_driver via_i2c_driver = {
235 .driver = {
236 .name = "viafb-i2c",
237 },
238 .probe = viafb_i2c_probe,
239 .remove = viafb_i2c_remove,
240};
241
242int viafb_i2c_init(void)
243{
244 return platform_driver_register(&via_i2c_driver);
245}
246
247void viafb_i2c_exit(void)
248{
249 platform_driver_unregister(&via_i2c_driver);
227} 250}
diff --git a/drivers/video/via/via_i2c.h b/drivers/video/via/via_i2c.h
index 0685de9a0c7a..b2332cce9d18 100644
--- a/drivers/video/via/via_i2c.h
+++ b/drivers/video/via/via_i2c.h
@@ -35,8 +35,6 @@ int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata);
35int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data); 35int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data);
36int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len); 36int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len);
37 37
38struct viafb_par; 38extern int viafb_i2c_init(void);
39int viafb_create_i2c_busses(struct viafb_dev *vdev, struct via_port_cfg *cfg); 39extern void viafb_i2c_exit(void);
40void viafb_delete_i2c_busses(void);
41struct i2c_adapter *viafb_find_adapter(enum viafb_i2c_adap which);
42#endif /* __VIA_I2C_H__ */ 40#endif /* __VIA_I2C_H__ */